// Copyright (c) CNES 2008 // // This software is part of CelestLab, a CNES toolbox for Scilab // // This software is governed by the CeCILL license under French law and // abiding by the rules of distribution of free software. You can use, // modify and/ or redistribute the software under the terms of the CeCILL // license as circulated by CEA, CNRS and INRIA at the following URL // 'http://www.cecill.info'. function [paths] = CL_path(names, directories, opt, err, hid) // File paths (search in selected directories) // // Calling Sequence // paths = CL_path(names [, directories, opt, err, hid]) // // Description // //

Looks for files in directories and returns their paths.

//

names can be a file name or a string containing wildcards ("*").

//

If directories is omitted or is a blank string, %CL_PATH is searched if it is defined. // If %CL_PATH does not exist, the working directory is searched.

//

//

There are 2 possible search options:

//

opt = "std": Returns the path of the first file found (sub-directories are not searched).

//

opt = "all": Returns the paths of all the files found (sub-directories at any depth are searched. // In this case, the search is "breadth-first".

//

//

If no file is found, the returned value is []. An error is raised if err == %t and opt == "std".

//

If hid is %t, hidden directories (whose name begin with ".") are searched, otherwise // they're not, even if they belong to the "directories" list.

//

If a directory name (in "directories") end with "/*", its name is replaced by the list of all its sub-directories.

//
//
// // Parameters // names: (string) Name(s) of file(s) to be looked for (may contain wildcards). (1xN) // directories: (string, optional) Directories to be searched. Default is "" (meaning: %CL_PATH if exists, '.' otherwise) (1xP) // opt: (string, optional) Search option: "std" or "all". Default is "std" (1x1) // err: (boolean, optional) %t is an error is raised if no file is found. Default is %t (1x1) // hid: (boolean, optional) %t if hidden directories are included in the search. Default is %f (1x1) // paths: (string) File path(s) or [] if no file is found (1xQ) // // Authors // CNES - DCT/SB // // Examples // // Looks for "readme.txt" in CL_home() (sub-directories not searched) // CL_path("readme.txt", CL_home()) // // // Returns all "*.scd" file (deep search) // CL_path("*.scd", CL_home(), "all") // --------------------------------------------- // internal functions // --------------------------------------------- // file part of a name function [fpart] = Fname(name) [dpart, f1, f2] = fileparts(name); fpart = f1 + f2; endfunction // Returns the list (1xN vector) of sub-directories // d: name of 1 directory (supposed to exist) // hid: %t if "hidden" directories are included. function [subd] = Listsubdirs(d, hid) subd = []; subd = matrix(findfiles(d, "*"), 1, -1); if (subd <> []) I = find(isdir(d + filesep() + subd)); subd = subd(I); if (~hid) I = find(part(subd,1) <> "."); subd = subd(I); end end if (subd <> []) subd = d + filesep() + subd; end endfunction // Looks for files in one directory and returns the paths // name: (string) 1x1 // d: (string) directory (supposed to exist) 1x1 // NB: name can have the form: "dir/name" function [fil] = Filepath0(name, d) fil = []; if (dirname(name) <> ".") // name contains a directory part d = fullfile(d, dirname(name)); name = Fname(name); end f = findfiles(d, name); if (f <> []) fil = d + filesep() + matrix(f, 1, -1); end endfunction // find a file in list of directories and returns the paths // looks for name at depth 0 (in dirs(1), dirs(2), ...), // then depth 1, then depth 2, etc... // name: (string) 1x1 // dirs: (string) 1xN // nres == 1 if one result returned, 0 otherwise // maxdepth = 0 => only search in dirs(1), dirs(2), ... function [paths] = Filepath1(names, dirs, maxdepth, nres, hid) paths = []; for (name = names) for (d = dirs) p = Filepath0(name, d); if (p <> []) paths = [paths, p]; if (nres == 1); break; end end end end // continue searching if: // - max depth not reached and // - nres == 0 | (nres == 1 & file not yet found) if (maxdepth > 0 & (nres == 0 | paths == [])) // list all sub-dirs first subdirs = []; for (d = dirs) subdirs = [subdirs, Listsubdirs(d, hid)]; end // search sub-dirs if (subdirs <> []) p = Filepath1(names, subdirs, maxdepth-1, nres, hid); if (p <> []) paths = [paths, p]; end end end if (nres == 1) paths = paths(1); end endfunction // --------------------------------------------- // main // --------------------------------------------- if (~exists("directories", "local")); directories = ""; end if (~exists("opt", "local")); opt="std"; end if (~exists("err", "local")); err=%t; end if (exists("hidden", "local")) CL__warning("Deprecated use of ''hidden'' argument"); hid = evstr("hidden"); end if (~exists("hid", "local")); hid=%f; end if (opt <> "std" & opt <> "all") CL__error("Invalid value for argument ''opt''"); end if (typeof(err) <> "boolean" | typeof(hid) <> "boolean" | typeof(err) <> "boolean") CL__error("Invalid argument type"); end if (typeof(names) <> "string" & names <> []) CL__error("Invalid type for argument ''names''"); end if (typeof(directories) <> "string" & directories <> []) CL__error("Invalid type for argument ''directories''"); end // error if more than one row if (size(names,1) > 1 | size(directories,1) > 1) CL__error("Invalid arguments sizes (names or directories)"); end // directory = white space => %CL_PATH if (size(directories,2) == 1 & stripblanks(directories(1),%t) == "") if (exists("%CL_PATH")) directories = matrix(%CL_PATH, 1, -1); else directories = "."; end end // default: one result returned at depth=0 maxdepth = 0; nres = 1; if (opt == "all") maxdepth = 50; // same as infinity in practice (avoid infinite loop) nres = 0; // means : any number of results end // default result paths = []; // Note: algo works if directories or names is [] // => nothing special to do // replaces "/*" in directory names. // removes hidden directories from list (if not wanted) dirlist = []; for (d = directories) dname = Fname(d); // name after last "/" if (dname == "*") dirlist = [dirlist, Listsubdirs(dirname(d), hid)]; elseif (dname == "." | dname == "..") dirlist = [dirlist, d]; elseif (hid | part(dname,1) <> ".") dirlist = [dirlist, d]; end end // keep existing directories only if (dirlist <> []) I = find(isdir(dirlist)); dirlist = dirlist(I); end // search ... paths = Filepath1(names, dirlist, maxdepth, nres, hid); // error if no file found (and err is %t) if (err & paths == [] & opt == "std") CL__error("File ''" + strcat(names," ") + "'' not found"); end endfunction