;+
;
; @file_comments
; based on FILE_SEARCH, but it is possible to specify
; a set of possibles names and a different set of
; possibles directories names.
;
; By default look for files included in !path
;
; all FILE_SEARCH keywords can be used.
;
; @categories
; find a file
;
; @param FILEIN {in}{required} {type=scalar string or array of strings}
; File name[s] to match. Input names specifications may contain
; wildcard characters, enabling them to match multiple files
; (see FILE_SEARCH for more informations). By default and if
; necessary, find is looking for filename and also for filename
; completed with '.pro'
;
; @keyword FIRSTFOUND
; activate this keyword to stop looking for the file as soon as we
; found one. Return a scalar string containing the first file found
;
; @keyword IODIRECTORY {type=scalar string or array of strings} {default=['.',!path]}
; Directories names where we are looking for the file.
; Different directories can be separated by
; path_sep(/search_path) (':' on unix type machine) as it is done
; to define !path.
; Note that if filename's dirname is different from '.', this
; keyword is not taken into account.
;
; @keyword LOOKALLDIR
; activate to look for the file (with a recursive search if needed)
; in . iodir, homedir, !path + the DATA:TestsData directory if it exists.
;
; @keyword NOPRO
; activate to avoid the automatic search of filename completed with '.pro'
;
; @keyword ONLYPRO
; force to look only at file ending with .pro
;
; @keyword ONLYNC
; force to look only at file ending with .nc
;
; @keyword RECURSIVE
; performs recursive searching of directory hierarchies.
; In a recursive search, find looks recursively for any and all
; subdirectories in the file hierarchy rooted at the IODIRECTORY argument.
;
; @keyword REPERTOIRE
; obsolete. keep for compatibility, use IODIRECTORY keyword
;
; @keyword UNIQUE
; activate to make sure that each element of the output vector is unique.
;
; @keyword TRYFIND
; if the file was not found and this keyword is activated, find
; will call
; itself with the keywords /LOOKALLDIR and /FIRSTFOUND to try to find
; the file we are looking for. Note that if the file was found at the
; first try this keyword as no effect (which is not the case with LOOKALLDIR)
;
; @keyword _EXTRA
; Used to pass keywords
;
; @returns
; A scalar or array variable of string type, containing the
; name (with the full path of the matching files. If no files
; exist with names matching the input arguments, find returns
; the scalar string : 'NOT FOUND'
;
; @examples
;
; IDL> print, find('*loadct')
; /usr/local/rsi/idl_6.0/lib/utilities/xloadct.pro
; /usr/local/rsi/idl_6.0/lib/loadct.pro
; IDL> print, find('*loadct', iodir=!dir,/recursive)
; /usr/local/rsi/idl_6.0/lib/loadct.pro
; /usr/local/rsi/idl_6.0/lib/utilities/xloadct.pro
; IDL> print, find('*loadct.pro')
; /usr/local/rsi/idl_6.0/lib/utilities/xloadct.pro
; /usr/local/rsi/idl_6.0/lib/loadct.pro
; IDL> print, find('*loadct',/nopro)
; NOT FOUND
; IDL> print, find('*loadct', iodir = '/usr/local/rsi/idl_6.0/lib')
; /usr/local/rsi/idl_6.0/lib/loadct.pro
; IDL> print, find('*loadct', iodir = '/usr/local/rsi/idl_6.0/lib', /test_write)
; NOT FOUND
; IDL> print, find('*loadct', iodir = '/usr/local/rsi/idl_6.0/lib', /recursive)
; /usr/local/rsi/idl_6.0/lib/loadct.pro
; /usr/local/rsi/idl_6.0/lib/utilities/xloadct.pro
; IDL> print, find('mesh*', iodirectory = [iodir, !path])
; /Users/sebastie/DATA/ORCA2/meshmaskORCA2closea.nc
; /Users/sebastie/IDL/meshmaskclosesea.pro
; /Users/sebastie/IDL/meshmaskclosesea.pro~
; /Users/sebastie/SAXO_RD/Obsolete/meshlec.pro
; /usr/local/rsi/idl_6.0/lib/mesh_obj.pro
;
; @history
; Sebastien Masson (smasson\@lodyc.jussieu.fr)
; - 28/4/1999
; - 6/7/1999: compatibility mac and windows
; - June 2005: Sebastien Masson: cleaning, use for file_* functions
;
; @version
; $Id$
;
;-
FUNCTION find, filein, IODIRECTORY=iodirectory, RECURSIVE=recursive $
, REPERTOIRE=repertoire, NOPRO=nopro, ONLYPRO=onlypro $
, ONLYNC=onlync, UNIQUE=unique, FIRSTFOUND=firstfound $
, LOOKALLDIR=LOOKALLDIR, TRYFIND=tryfind, _EXTRA=ex
;
compile_opt idl2, strictarrsubs
;
; define where we look for the file
cd, current = current
current = current + path_sep()
CASE 1 OF
keyword_set(lookalldir):BEGIN
@cm_general
dirnames = [current, iodir, homedir, !path]
tstdtadir= file_dirname(find('find', /onlypro), /mark_directory)
parent = path_sep(/parent_directory)+path_sep()
tstdtadir = (file_search(tstdtadir+parent+parent+'DATA/TestsData'))[0]
IF tstdtadir NE '' THEN dirnames = [tstdtadir, dirnames]
END
keyword_set(iodirectory): dirnames = iodirectory
keyword_set(repertoire): dirnames = repertoire
ELSE: dirnames = [current, !path]
ENDCASE
tmp = dirnames
dirnames = 'dummy'
FOR i = 0, n_elements(tmp)-1 DO $
dirnames = [dirnames, strsplit(tmp[i], path_sep(/search_path), /extract)]
dirnames = dirnames[1:*]
;
fileout = 'dummy'
FOR i = 0, n_elements(filein)-1 DO BEGIN
dir = file_dirname(filein[i])
base = file_basename(filein[i])
; try to complete the file name with .pro or .nc if needed...
CASE 1 OF
keyword_set(onlypro):BEGIN
promiss = strpos(base, '.pro', /reverse_search)
promiss = promiss - (strlen(base) - 4)
bad = where(promiss NE 0 OR strlen(base) LE 4, cnt)
IF cnt NE 0 THEN base[bad] = base[bad] + '.pro'
end
keyword_set(onlync):BEGIN
ncmiss = strpos(base, '.nc', /reverse_search)
ncmiss = ncmiss - (strlen(base) - 3)
bad = where(ncmiss NE 0 OR strlen(base) LE 3, cnt)
IF cnt NE 0 THEN base[bad] = base[bad] + '.nc'
END
ELSE:if strmid(base, 0, 1, /reverse_offset) NE '*' $
AND NOT keyword_set(nopro) THEN base = base + '{.pro,}'
ENDCASE
; use dirnames only if dir eq '.'
IF dir EQ '.' THEN BEGIN
if keyword_set(recursive) THEN $
found = file_search(dirnames, base, _extra = ex) $
ELSE found = file_search(dirnames + '/' + base, _extra = ex)
ENDIF ELSE found = file_search(dir + '/' + base, _extra = ex)
IF found[0] NE '' THEN BEGIN
IF keyword_set(firstfound) THEN return, found[0]
fileout = [fileout, found]
ENDIF
ENDFOR
IF n_elements(fileout) EQ 1 THEN fileout = 'NOT FOUND' $
ELSE fileout = fileout[1:*]
;
IF n_elements(fileout) GT 1 THEN BEGIN
IF keyword_set(unique) THEN fileout = fileout[uniq(fileout, sort(fileout))]
ENDIF ELSE fileout = fileout[0]
;
IF keyword_set(lookalldir) AND fileout[0] EQ 'NOT FOUND' $
AND NOT keyword_set(recursive) THEN $
filout = find(file_basename(filein[0]), /lookalldir $
, /recursive, _extra = ex)
;
IF keyword_set(tryfind) AND fileout[0] EQ 'NOT FOUND' THEN BEGIN
fileout = find(file_basename(filein[0]), /lookalldir, /firstfound, _extra = ex)
fileout = fileout[0]
ENDIF
;
RETURN, fileout
END