Fundamentals of find

If the GUI search tool (I hear this from Mac users) is not doing what you want, you can try using the command line. The find command can do very many things, some quite complicated. For our purposes, we just want to use it to search for files in a tree of directories. find will search all directories that are within a specified directory.

Here is a suggested procedure.

(1) Open a terminal – this is left as an exercise for the reader.

(2) Type pwd at the prompt (I will use $ to represent the prompt) and hit Enter. pwd tells you where you are now in the file tree. For example, if I do it now on my computer, I get this:

$ pwd

You will get something different.

(3) Use the cd (change directory) command to move to the region of the file tree you want to search. For example, I can move to /home and then check that I am there:

$ cd /home
$ pwd

(4) Now, you can search for the files. The form of a find command is:

$ find <directory> <flag> <pattern>

We have fixed the <directory> part by cding to where we want to search. On the command line ‘.’ means ‘current directory’. We want to find files by name, so we use the ‑name flag, and then our search text. So:

$ find . -name zmc

will find all files in the current file tree that are called ‘zmc’, and show me their paths (it turns out there are none). It will not find ‘ZMC’, ‘Zmc’, ‘zmcd’ etc. It will find an exact match. If I want ‘ZMC’ I search for ‘ZMC’ not ‘zmc’.

(5) Let's say we wanted to search for InDesign files. That is, files whose names end in (lower case) ‘indd’. We run:

$ find . -name "*indd"

(Note the double quotes – this is a good habit). The ‘*’ means ‘anything’, so this will find all files that end in ‘indd’. For example, if I change my ‘zmc’ search to ‘zmc*’ I get more results:

$ find . -name "zmc*"

(6) I can specify more detail to narrow my search. For example:

$ find . -name "zmc*mod"

So now I have found files starting with ‘zmc’ and ending in ‘mod’.

(7) A '?' stands for any 1 character, so for example:

$ find . -name "fr?d"

The leading ‘./’ means they are in my current directory – the one I cded into.

The ‘?’ demands a character.

$ find . -name "fr?d?"

finds nothing because none of the file names has a fifth character. On the other hand, ‘*’ matches any number of characters, including none:

$ find . -name "fr?d*"

(8) I can use as many ‘?’ as I like:

$ find . -name "?r?d"

All of ‘Grid’, ‘fred’, ‘frad’ and ‘frod’ match the pattern. ‘????’ would match all four-character file names. Similarly:

$ find . -name "fr?d????"

The four ‘?’ match ‘.icn’ but nothing else.

(9) I can change the flag ‘-name’ to ‘-iname’ where you can think of the ‘i’ as meaning 'insensitive'. This is not a search done by a man, but one that is case insensitive. So I can repeat an earlier search but with this flag:

$ find . -iname "zmc*"
(etc etc etc!)

Note that find also matches paths (that is, directory names). ‘./username/installs/ZMC’ is a directory.

(10) You can replace the ‘.’ in the find command with the path to the directory you want to search, rather than cding into the directory. For example:

$ find /home -iname "*.docx"

This will find anything within /home ending in ‘.docx’, ‘.DOCX’, ‘.dOCx’, ‘DoCx’, etc.

(11) If you get too many results, you can deal with this in several ways. Making the search more specific is one. One is by adding ‘| more’ to the end of your command (‘|’ is the vertical bar character, called a pipe):

$ find /home -iname "*.docx" | more

You can pipe the output of find through the grep command. It will pick out results that match another criterion.

$ find /home -iname "*.docx" | grep -i "draft"

(again, ‘i’ means insensitive). This will find results that have ‘.docx’ on the end and ‘draft’ somewhere else. This is handy because you can use it to select based on directory rather than file name. It would find files ending in ‘.docx’ that have ‘draft’ in the name of the file and/or in the name of the path.