;+ ; NAME: ; SetFileSpec ; PURPOSE: ; Split file names into file components. ; Optionally parse the file names. ; CATEGORY: ; gen/idl/toolbox/files ; CALLING SEQUENCE: PRO SetFileSpec, FileSpec, FileParts, $ parse = Parse , $ nosave = NoSave, $ strict = strict, $ status = Status ; INPUTS: ; FileSpec string array or scalar, containing file names ; (read-only) ; OPTIONAL INPUT PARAMETERS: ; /parse if set, the file names are parsed. ; parsing is successful if ; - The directory exists ; - There is write access to the directory ; - The file name is valid (the file may or may not exist) ; (if no file name is specified this step is skipped) ; If the parsing is succesful, missing file parts will ; be added to the FileParts array; if not all parts are ; set to the null string. ; /nosave by default, the FileParts array returned as ouput ; is saved internally in a common block (which can ; be accessed with GetFileSpec and PutFileSpec). ; if nosave is set, the internal data are not overwritten. ; /strict by default the file type is the part of the ; filename trailing the last dot, i.e. if the file name ; is file.txt.gz, the file type is .gz. ; If /strict is set the type becomes the part following ; the first dot, i.e. the type is .txt.gz. ; OUTPUTS: ; FileParts string array with one dimension more than ; FileSpec; the extra first dimension has 6 elements, ; containing node, device, directory, name, type, version ; !!! the FileParts argument is sometimes useful in ; combination with the /nosave keyword. Preferably this ; argument should not be used; instead use GetFileSpec ; and PutFileSpec to manipulate the same information. ; OPTIONAL OUTPUT PARAMETERS: ; status=Status long integer array with same dimensions as FileSpec. ; If keyword Parse set: ; 0 : indicates that parsing failed ; 1 : indicates that parsing was succesfull ; If keyword Parse not set, all values are set to 1 ; CALLS: ; InitVar, IsType ; os_separator, SetFileSpec, CheckDir, FindAllFiles, strposn, SyncDims ; INCLUDE: @compile_opt.pro ; On error, return to caller @filespec_common.pro ; Common block with arrays File and Parts ; SIDE EFFECTS: ; Internal data are maintained internally (a copy of FileParts) ; RESTRICTIONS: ; FileSpec containing relative directory specifications ; (e.g. [], [-] on VMS, or . and .. on Win32 and Unix), cause ; problems for GetFileSpec. If these are present, then /parse ; should be used to remove them. ; PROCEDURE: ; > Parsing: the existence check for the directory is done using CheckDir. ; The fully-parsed directory returned by CheckDir is used, so the parse ; keyword can be used to expand environment variables, e.g. ; SetFileSpec, '$dat/tmo/*.nic', /parse ; print, GetFileSpec() ; would print (provided the directory exists): ; /big/oftp/dat/tmo/*.nic ; > If a wildcard is specified in the file name then only the directory ; is parsed. ; > For an existing file the full file name is obtained using FindAllFiles. ; If the file does not exist, an attempt is made to open ; the file with OPENW to establish that the syntax is valid; ; FindAllFiles is used to obtain the full file name before closing and ; deleting the file again. ; > The filenames are split up into parts by a series of strposn calls ; > FileSpec='' (null string) is interpreted as the current working directory, ; and will always return status=1. ; MODIFICATION HISTORY: ; DEC-1997, Paul Hick (UCSD/CASS) ; FEB-2002, Paul Hick (UCSD/CASS) ; Remove bug which caused problems when multidimensional arrays ; of filenames were processed. ; JAN-2003, Paul Hick (UCSD/CASS; pphick@ucsd.edu) ; If a wildcard (*) is specified in the filename part then only the ; directory is checked when the /parse keyword is set. ;- InitVar, Parse , /key InitVar, NoSave , /key InitVar, strict , /key FileName = FileSpec sFile = size(FileName) nFile = sFile[sFile[0]+2] ; # elements in FileName ArrayInput = sFile[0] NE 0 Status = replicate(1, nFile) SyncDims, Status, size=sFile ; Same structure as FileSpec IF Parse THEN BEGIN ; Ugly, but it seems the most practical approach. FOR i=0,nFile-1 DO BEGIN SetFileSpec, FileName[i], Parts, /nosave Status[i] = CheckDir( Parts[0]+Parts[1]+Parts[2], tmp, silent=1) CASE Status[i] OF 0: FileName[i] = '' ; Directory does not exist 1: BEGIN ; Directory exists Parts345 = Parts[3]+Parts[4]+Parts[5] IF Parts345 EQ '' OR Parts345 EQ '.' OR Parts345 EQ ';' OR Parts345 EQ '.;' THEN $ ; No filename specified FileName[i] = tmp $ ; Full directory name ELSE IF strpos(Parts345,'*') ne -1 THEN $ FileName[i] = filepath(root=tmp, Parts345) $ ELSE BEGIN ; Check filename tmp = FindAllFiles(FileName[i]) IF tmp[0] NE '' THEN $ ; File already exists FileName[i] = tmp[0] $ ELSE BEGIN ; File doesn't exist openw, /get_lun, iu, FileName[i], /delete, error=Error Status[i] = Error EQ 0 ; Open as scratch file CASE Status[i] OF ; New file created; pick up file name 0: FileName[i] = '' ; Open failed 1: FileName[i] = (FindAllFiles(FileName[i]))[0] ENDCASE IF IsType(iu, /defined) THEN free_lun, iu ; Close/delete scratch file ENDELSE ENDELSE END ENDCASE ENDFOR ENDIF IF ArrayInput THEN tmp = reform(FileName, nFile) ELSE tmp = FileName i = strposn(tmp, '::' , FileParts, tmp, /trailing, /last) ; VMS Node i = strposn(tmp, ':' , Front , tmp, /trailing, /last) ; VMS Device FileParts = [FileParts,Front] i = strposn(tmp, os_separator(/dir), Front , tmp, /trailing, /last) ; [,\ or / FileParts = [FileParts,Front] ; Directory i = strposn(tmp, '.' , Front , tmp, /leading, /front, last=1-strict) FileParts = [FileParts,Front] ; File name i = strposn(tmp, ';' , Front , tmp, /leading, /front) i = where(Front EQ '' AND FileParts[3,*] NE '') ; File type is at least a '.' IF i[0] NE -1 THEN IF !version.os EQ 'vms' THEN Front[i] = '.' FileParts = [FileParts,Front] ; File type FileParts = [FileParts,tmp] ; File version IF ArrayInput THEN FileParts = $ transpose( reform( FileParts, nFile, 6 ) ) ;reform( transpose( reform( FileParts, nFile, 6 ) ), [6,sFile[1:sFile[0]]] ) IF NOT NoSave THEN BEGIN ; File is a two-dim array [6,*]; sFile is the size vector of the input array ; The size vector is used by GetFileSpec to return arrays of the same type as ; the input to SetFileSpec. File = FileParts ; Fill common block FileSize = sFile ENDIF RETURN & END