I'm using bash for Mac OS X 10.6.8.

Using the find command, I would like to search for files that match *.XML. However, I would like to match only those files in the 16xxxx sub-directory and not 16yyyy from some base directory.


The results I'm looking for would be EX1.XML and EX2.XML (full path name excluded for clarity).

This is in the context of a BASH script which would make it convenient if I could enter 16xxxx/*.XML as the expression to pass to -name in the find command:

find basedir -name '16xxxx/*.XML'

However, this does not return any matches because the shell doesn't match the / character. Is there some argument to pass to find or a way to escape the 16xxxx/\*.XML expression that will return the results I need?


The -name option is never going to work past the first /. As always, man pages are your friends:

 -path pattern
         True if the pathname being examined matches pattern.  Special shell pattern matching characters
         (``['', ``]'', ``*'', and ``?'') may be used as part of pattern.  These characters may be
         matched explicitly by escaping them with a backslash (``\'').  Slashes (``/'') are treated as
         normal characters and do not have to be matched explicitly.

I usually prefer compatibility with GNU find, and therefore use the -wholename option. Nothe that these also exist in case-insensitive mode: -iwholename and -ipath.

So in your case, you'd do (remember that wholename matches the whole path, so you have to add the wildcard * at the beginning):

karolos$ find basedir -type f
karolos$ find basedir -wholename "*16xxxx/*.XML"

Another way to achieve what you want is to use find in combination with grep (note that I had to alter the regular expression, adding a . (for any caracter) before the wildcard *):

karolos$ find basedir | grep '16xxxx/.*.XML'

Finally, depending on your needs, there is even the possibility that you don't even need to use find (if you don't need the extra flexibility). You can then use bash filename expansion as follows:

karolos$ echo basename/*16x*/*XML
basename/16xxxx/EX1.XML basename/16xxxx/EX2.XML
  • Thanks for this. I tried -wholename during my efforts yesterday but didn't try the wildcard. I tried my best to avoid the RTFM comments (I read the manual), but I'll need to try harder ;) – stever Feb 22 '12 at 16:17
  • @stever: You're welcome. Manual pages for GNU tools are usually well documented, but the *nix jargon is not always straightforward at first. The leading wildcard catch is indeed something easy to miss. – Karolos Feb 22 '12 at 18:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.