How to Recursively Find All Files in Directories/Subfolders by Wildcards
Users may come across a situation where they would like to find all files in a directory, folder, or subfolder structure, that match a particular string but with variations to the file names, a situation perfect for finding files based on wildcard matches.
For example, maybe you’d like to locate all files on a file system containing the word “invoice” regardless of where in the filename the text of ‘invoice’ appears (eg, files named like the following; invoice1-2023.pdf, big-invoice-wow.pdf, yourfavoriteinvoice.pdf, invoice-2-22.pdf, etc).
This article will show you how to use the command line to find files recursively in directories and subdirectories by using wildcards that match a string of text that could appear anywhere in the filename itself, with several practical examples.
How to Recursively Find All Files Matched by Wildcard
We’ll use the find command, which, as you may have guessed by the name, allows you to find files in the file system directly from the command line.
find . -name "text*"
This command is broken down as follows:
find [directory] (In this case “.” represents the current directory) -name “[matched text and wildcards]” (In this case, filenames matching ‘text’ followed by anything).
To find matches with wildcards before and after the particular text match, use the following, replacing “text” with the appropriate syntax to match files for your use case:
find . -name "*text*"
Using the example mentioned in the introduction, let’s say you’re trying to track down all files containing the text “invoice” in the file name, no matter where they are located within the users entire home directory structure. The syntax for such a search could look something like the following:
find ~/ -name "*invoice*"
Executing that command may see something like the following as command output:
/Users/Paul//Library/Application Support/CloudAppHoldingFiles/mystery-invoice-2023.pdf
/Users/Paul//Library/Application Support/WhoKnows/invoice-2024.pdf
/Users/Paul/Documents/big-invoice-wow.pdf
/Users/Paul/Documents/Misc/small-invoice-dontforget.pdf
/Users/Paul/Desktop/YouForgotAboutThisInvoice.pdf
/Users/Paul/Desktop/AnotherInvoice.pdf
/Users/Paul/Documents/Invoices/invoice-1-23.pdf
/Users/Paul/Documents/Invoices/invoice-3-23.pdf
/Users/Paul/Documents/Invoices/invoice-4-23.pdf
/Users/Paul/Documents/Invoices/invoice-5-23.pdf
/Users/Paul/Documents/Invoices/invoice-6-23.pdf
As you can see, this command and file finding is particularly helpful if you have files scattered around in a filesystem that you want to track down all of by name match and wildcards.
While you can certainly use Spotlight or Finder to try and track down all matches too, with some of the more recent changes to Spotlight it seems more difficult to actually find all files, and while the Finder search can use wildcards to find name matches too, the command line is simply easier for many users. If Finder is easier, you may find this trick to list all files in subdirectories recursively to be helpful as well.
If you have another preferred method for searching files recursively in directories by wildcard matches, share your approach in the comments below!
Are there any wildcard search options in finder or spotlight?
In zsh (which is now the default shell), you can just do this:
ls **/*invoice*
With the goven command you can miss files due to capaitalization, and you can also get a lot of unwanted results due to permission errors.
I use a more universal command line:
sudo find -x / -iname “*invoice*” 2>/dev/null
I run it once without the 2>/dev/null and check that I’m not getting an error about the command itself, then stop it and run it again with 2>/dev/null to strip out all the error messages just saying “you don’t have permission to search this folder”
Many moons ago you could use wild cards when doing searches in MS-Dos, why hasn’t that been implemented in Spotlight.
The above is good, but you have to realize that probably 90% of Apple users don’t use terminal, thus will get lost doing so.
-iname is case-insensitive