BSD DevCenter
oreilly.comSafari Books Online.Conferences.

advertisement


FreeBSD Basics

Finding Things in Unix

02/21/2002

One of the most useful utilities to be found on any Unix system is the find command.

In the next two articles, I'd like to work you through the syntax of this command and provide you with some practical examples of its usage.

The command itself has a very simple syntax:

find where_to_search expressions

The expressions are the part that can look confusing the first few times you use find. They are also the part that can vary from Unix system to Unix system, so you may want to take a quick peek at find's manpage if you find yourself on a new system. The most common expressions that you can use on your FreeBSD system are as follows:


-namemust be quoted when using wildcards
-typee.g. f=file d=directory l=link
-username or UID
-groupname or GID
-permspecify permissions
-sizerounded up to next 512 byte block or use c to specify bytes
-atimelast time file was read
-ctimelast time file's owner or permissions were changed
-mtimelast time file was modified
-newerfind files newer than given file
-deleteremove files found
-lsgives same output as ls -dgils
-printdisplays results of find command
-exec command {} \;to execute a command; note the required syntax
-okuse instead of exec to be prompted before command is executed
-depthstarts at lowest level in directory tree rather than root of given directory
-pruneused when you want to exclude certain subdirectories

I'll be giving examples that show how to use and combine these expressions. Before doing that, what can find be used for? If you use the whatis command to see what it does, the answer may surprise you:

whatis find
find(1)           - walk a file hierarchy

In a nutshell, find is meant to recursively search directories to find any files that meet your specified expressions. This may not seem like such a big deal, but there aren't that many Unix utilities that can "walk" through a directory and all of its subdirectories. This ability proves quite useful, as not only can you find files, but you can do something with them as you find them.

Let's start with some simple examples and then work our way towards some more seemingly-complicated expressions. The simplest find you can do is to simply type this:

find . -print

Since the "." represents your current directory, this find command will find all of the files in your current directory and all of its subdirectories, and then print the results to your screen.

On your FreeBSD system, -print is assumed if you forget to type it, so this command will also give the same result:

find .

However, it's a good idea to get in the habit of using -print, in case you ever need to do a find on a system that does not assume this action.

To find all of the files in your home directory, you should first make sure you are in your home directory, then repeat that find command, like so:

cd
find . -print

The cd command will always take you to your home directory. Since the find command can be used to do powerful things, it is always a good idea to first cd to the directory structure in which you wish to work. For the rest of this article, I will assume that you are in your home directory, so you won't inadvertantly affect any files on your FreeBSD system that don't reside in your home directory.

The above examples demonstrated how easy it is to use find, but usually you are looking for something specific when you invoke the find command. This is where the other expressions come into play. Let's try to find a file with a specific name:

touch file1
find . -name file1 -print		
./file1

Let's pick apart what I just did for a moment. I created an empty file named file1 using the touch command. I then told find to search my current directory (".") for a file named (-name) file1 and to print the results of the search to my screen. Also, I can tell that I only have one file named file1 in my home directory and all of its subdirectories, as only one result was displayed.

Often, when you need to use the find command, you are looking for more than one file. For example, you may want to find all of the files with a certain extension. I tend to download a lot of .pdf files and don't always remember to keep them in the same place. Occasionally, I like to collect them and put them in a directory I've created named pdfs. When this urge strikes, I can use the following find command to search my home directory and its subdirectories for all .pdf files:

find . -name "*.pdf" -print
./pdfs/50130201a.pdf
./pdfs/50130201b.pdf
./pdfs/50130201c.pdf
./pdfs/IWARLab.pdf
./pdfs/DoS_trends.pdf
./pdfs/Firewall-Guide.pdf
./2000_ports.pdf

It looks like I've been pretty good lately, as I only have one .pdf file that is not in my pdfs directory.

You'll note that in order to get this find command to work, I had to "quote" the "*" wildcard by typing "*.pdf" instead of just *.pdf. There are two other ways to quote, so the following two commands will yield the same results:

find . -name \*.pdf -print
find . -name '*.pdf' -print

Let's add to that original command and see how the output changes. What if I was only interested in seeing which .pdf files were not in the pdfs directory? Let's repeat that find command, but pipe the results to grep so only that one file will be displayed:

find . -name "*.pdf" -print | grep -v "^\./pdfs/" ./2000_ports.pdf

Well, that command worked, but that syntax looks pretty scary; we better pick it apart. Whenever you use grep -v, you are creating a reverse filter, meaning that you want it to show the opposite of what follows. In my case, I'm not interested in the files that reside in the ./pdfs/ directory; I want to find the files that aren't, so I used the reverse filter. You'll note that I also "quoted" the whole expression. I also added a bit extra, that ^\ stuff. The ^ tells grep to only search the very beginning of a line for my expression. The \ is an extra quote so that grep does not interpret the . as a special character. The whole thing put together told grep to just show me the files that don't live in the ./pdfs/ directory, so I received the desired output.

Pages: 1, 2

Next Pagearrow





Sponsored by: