;+ ; NAME: ; findfile_fix ; PURPOSE: ; Applies fix to output from IDL findfile procedure. ; CATEGORY: ; gen/toolbox/files ; CALLING SEQUENCE: FUNCTION findfile_fix, dir, file, old_files, count=count, ls_style=ls_style ; INPUTS: ; path ; file ; old_files array; type: string ; Output from findfile ; OPTIONAL INPUT PARAMETERS: ; count=count scalar; type: integer ; Output from findfile (# files) ; OUTPUTS: ; result array; type: string ; Corrected 'old_files' array ; OPTIONAL OUTPUT PARAMETERS: ; count=count scalar; type: integer ; # entries in new_files ; INCLUDE: @compile_opt.pro ; On error, return to caller ; CALLS: ; InitVar, SetFileSpec, GetFileSpec, FindAllSubdirs, where_common ; PROCEDURE: ; This is kludging at its best. On Linux (maybe even all Unix ; flavors??) a findfile call with a wildcard (in particular a ; single star) can pick up subdirectories: ; files = findfile('path/*') ; The result is a string array of the form: ; full_file_1 ; full_file_2 ; .. ; full_file_n ; (blank line) ; full_subdir_1: (sub dir name followed by colon) ; file_1_in_subdir_1 (file name without directory) ; file_2_in_subdir_1 (file name without directory) ; .. ; file_n_in_subdir_1 (file name without directory) ; (blank Line) ; full_subdir_2: (sub dir name followed by colon) ; etc. ; ; The list of full_file_n at the beginning may not be present. ; Moreover, if only one subdirectory matches the template then ; full_subdir_1 will be missing too, and only the list ; file_n_in_subdir_1 remains. In this last case it is impossible ; to reconstruct the full file names. An attempt is made to recover ; the name of the subdirectory using FindAllSubdirs. If not ; successful then these entries (the whole list of files) is discarded. ; ; If it is possible to reconstruct full paths, two approaches ; are possible depending on the setting of /ls_style. ; If /ls_style is NOT set, then all entries inside subdirectories ; are discarded, and only the subdirectory name itself is returned. ; ; If /ls_style IS set, then the content of subdirectories is also ; returned (converted to full paths by prefixing the names of the ; subdirectory). Blank lines are always removed. ; MODIFICATION HISTORY: ; SEP-2002, Paul Hick (UCSD/CASS) ; MAR-2003, Paul Hick (UCSD/CASS; pphick@ucsd.edu) ; Added a fix to make sure subdirectories have a trailing slash ; when output from findfile with only a directory (no filename) ; as argument is processed. ;- Path = dir+file InitVar, ls_style, /key InitVar, count, n_elements(old_files) IF count EQ 1 AND old_files[0] EQ '' THEN count = 0 IF count GT 0 THEN BEGIN IF strpos(old_files[0],':') EQ -1 THEN BEGIN IF file EQ '' THEN BEGIN ; If file='' then the whole content of a directory was retrieved ; (i.e, only the directory was specified in findfile without a ; wildcard spec). Make sure that the subdirectory entries have a ; a trailing slash. tmp = where_common(old_files+'/', FindAllSubDirs(dir)) IF tmp[0] NE -1 THEN old_files[tmp] = old_files[tmp]+'/' ENDIF ELSE BEGIN ; Check whether full paths can be reconstructed. If not, then attempt ; to recover. SetFileSpec, old_files[0] IF GetFileSpec(upto='directory') EQ '' THEN BEGIN SetFileSpec, Path sub = FindAllSubDirs(GetFileSpec(upto='directory')) i = (where( strpos(sub, strmid(Path,0,strpos(Path,'*')) ) EQ 0 ))[0] CASE i EQ -1 OF 0: BEGIN old_files = [sub[i]+':',old_files] count = count+1 END 1: BEGIN message, /info, 'not enough info to reconstruct full path; discarding:' print, path count = 0 END ENDCASE ENDIF ENDELSE ENDIF ENDIF CASE count OF 0 : new_files = '' ELSE: BEGIN new_files = old_files colon = strpos(new_files,':') length = strlen(new_files) trail = where( length GT 0 AND colon EQ length-1, ntrail ) IF ntrail GT 0 THEN BEGIN ; Count subdirectory entries (ending with a colon) message, /info, strcompress(ntrail,/rem)+' subdirectories fixed' trail = [trail, count+1] ; Locations of subdirectory names ENDIF FOR i=0,ntrail-1 DO BEGIN ; Loop over subdirectories i1 = trail[i ] i2 = trail[i+1] ; Subdirectory entries are preceeded by a blank line. ; If ls_style is not set, erase all files in subdirectores ; If ls_style is set give files in subdirectories a full file path IF i1+1 LE i2-2 THEN BEGIN CASE ls_style OF 0: new_files[i1+1:i2-2] = '' 1: new_files[i1+1:i2-2] = filepath( root=strmid(new_files[i1],0,length[i1]-1),new_files[i1+1:i2-2]) ENDCASE ENDIF ; Remove the trailing colon from subdirectories ; Add trailing slash. We need it to be able to discard ; directories in FindAllFiles when the /nodir keyword is set new_files[i1] = filepath(root=strmid(new_files[i1],0,colon[i1]),'') ENDFOR length = strlen(new_files) new_files = new_files[ where(length gt 0) ] count = n_elements(new_files) END ENDCASE RETURN, new_files & END