The most efficient way to solve probably depends on the operating system you are running Mathematica on. Linux offers an efficient way of finding one of more files using a regular expression file specification.
In it's simplest form the solution resolves to the following which stops once it has found one file:
findAFile[name_String, path_String: "/"] :=
ReadList["!find " <> path <> " -name \"" <> name <> "\" -print -quit", String]
An example of use would be:
findFiles["*[1-3].JPG"]
{"/data/bitmaps/for_filing/S1010001.JPG"}
This uses the ability of ReadList to directly take an operating system command, in this case find, run that command and return its output.
A more general solution allowing use of find's extensive options:
Options[findFiles] = {FindOptions -> "-print -quit"};
findFiles[name_String, path_String: "/",OptionsPattern[]] :=
ReadList["!find "<> path <> " -name \"" <> name <> "\" "<> OptionValue@FindOptions, String]
To find the first N files it is simple to use linux's head command as an option:
findFiles["*.jpg", "/mnt/ls3/data/bitmaps/animals", FindOptions -> " | head -4"]
{"/data/bitmaps/animals/birds/waterfowl/dsc04802.jpg",
"/data/bitmaps/animals/birds/waterfowl/dsc04803.jpg",
"/data/bitmaps/animals/birds/waterfowl/dsc04804.jpg",
"/data/bitmaps/animals/birds/waterfowl/dsc04805.jpg"}
Whilst the following would find only the directories below the given path:
findFiles["*", "/data/bitmaps/animals", FindOptions -> " -type d "]
{"/data/bitmaps/animals","/data/bitmaps/animals/birds","/data/bitmaps/animals/birds/general"}
>
Background
In the Linux case the operating system provides support for finding files in a number of ways.
Probably the most used of these are ls, find and locate.
find has a host of options to select by date, type, owner, depth, size and more. It allows logical combinations of options and even execution of commands on the found files. It offers a much richer search method than Mathematica's FindFile or FileNames, find.
Without too much effort we can leverage that capability.
Finding the first file
Linux offers several ways to find the first, or N, file(s) from a list.
Forcing find to abort after it's first result:
find / -name "*.jpg -print -quit "
By aborting find when head ( which just prints the first N lines of it's input ) has fulfilled it's line specification:
find / -name "*.jpg | head -1 "
Replacing -1 with -2 , -3 and so on, will return the first 2, 3 etc files found.
The specific file returned will depend upon the search order of directories which is system dependent.
The search order for any system can be determined by:
find path -type d where path represents the starting point in the directory structure for find to begin its search. Typically that might be the filesystem root directory / as in the previous examples.
An alternative approach using locate, which may have a different search order for directories, can be adopted with:
locate *.jpg --limit=1
// Firstafter the other code. Or do you mean you want to stop the search as soon as one file is found? – Mr.Wizard Jul 18 '12 at 05:43FileNames. Are you open to using external (command line) tools? What OS do you use? – Mr.Wizard Jul 18 '12 at 05:51Returndo with multiple arguments? – wxffles Jul 18 '12 at 06:35