BSD DevCenter
oreilly.comSafari Books Online.Conferences.


Find: Part Two
Pages: 1, 2

Let's take a look at some more switches. The -ls switch will give the inode number, number of blocks, permissions, number of hard links, owner, group, size in bytes, last modification time, and name for each file that is found. For example, the following command will show me the first ten directories in my home directory; you'll note that I specified that I only wanted to see directories by using the -type d switch.

find . -type d -ls | head
976142  8 drwxr-xr-x  39 genisis  wheel    4096 Mar  3 17:52 .
1413099  2 drwxr-xr-x  2 genisis  wheel   512 Mar  3 13:38 ./pdfs
373539  2 drwxr-xr-x  2 genisis  wheel    512 Feb  6 12:38 ./tst
1087249  2 drwxr-xr-x  2 genisis  wheel   512 Oct  4 07:29 ./perlscripts
650764  2 drwx------  2 genisis  wheel  512 Mar  3 17:52 ./mail
706616  2 drwx------  4 genisis  wheel  512 Sep 22 14:29 ./.kde
706635  2 drwx------ 11 genisis  wheel  512 Nov  7 12:36 ./.kde/share
706636  4 drwx------  3 genisis  wheel  1536 Mar  2 18:38 ./.kde/share/config
785986  2 drwx------  2 genisis  wheel  512 Sep 22 14:36 ./.kde/share/config/colors
706682  2 drwx------  3 genisis  wheel  512 Mar  2 18:36 ./.kde/share/fonts

Let's get a little fancier with the -ls switch. Earlier in the article, we piped some output to wc -l to see how many files contained a certain expression. Let's be a bit more particular and see how many subdirectories are in my home directory:

find . -type d -print | wc -l

Actually, there are only 255 subdirectories, as one of them is my current directory. Now, let's get a better idea of how this directory structure is laid out using this command:

find . -type d -ls | awk '{print $4 - 2, $NF}' | sort -rn | head
37 .
26 ./.kde/share/apps/kio_http/cache
18 ./.kde/share/apps
15 ./.gimp-1.2
9 ./tmp/tst
9 ./.kde/share
8 ./tmp/tst/h
8 ./tmp/tst/g
8 ./tmp/tst/f
8 ./tmp/tst/e

Wow, that's pretty cool. It looks like there are 37 subdirectories in my home directory (.), 26 subdirectories in the .kde/share/apps/kio_http/cache subdirectory, etc. Now, let's see how this find command worked. I started by using the -ls switch, which gave a fair bit of information regarding each directory as it was found. This information was piped to the awk utility, which is used to extract the data from certain fields. You'll note that in the original -ls output, the results were in certain fields: inode number, number of blocks, permissions, number of links, etc. I told awk to take the information from column 4 (which contains the number of links and is $4 to awk) and subtract 2 from that value (as I'm not interested in the directories . or ..). I also wanted to know the name of each directory; since this was the very last column, I used $NF to represent that field. By placing these instructions within the curly braces {}, I told awk to do this to every file that it received from the find command. I then piped the results from awk to the sort command; by using -rn, I told sort to sort the numerical output from largest to smallest so I could see which directories had the most subdirectories. I didn't want to bore you with all the output, so I also piped the final results to the head command so it would only display the first ten.

Another find switch is the -perm switch. An example is to search for any files that have their permissions set to 777, that is, set to read, write, and execute for everyone. This can be easily done with this command:

find . -perm 777 -print

The above command searches for files with the exact permissions of 777. If you are concerned with only a certain bit, rather than all the permission bits, you can do something like this:

find . -perm -4000 -print

This example will only yield files that have the SUID bit set. (Read more about permissions in a previous article.) Another handy find command is this one:

find . -perm -0002 -print

It will find all files that are writable by others. Note that you can use -0002, -002, -02, or -2 and receive the same result as leading 0s are assumed.

The last two switches I want to cover in today's article are useful when backing up or replicating directory structures. Let's start with -depth. Let's say I want to back up my entire home directory to a mounted directory named /backup. I can do this:

find . -depth -print | cpio -dump /backup

This command may also work without the -depth switch, but not always. By default, find lists the files it finds by starting at the point mentioned in the find command, in my case . or my home directory. That is, it lists first the directory, and then the contents of that directory. If it encounters a directory that has read-only permissions, find will still provide a list of the contents of that directory to the cpio command, but the cpio command won't have permission to replicate the files in that subdirectory. It is interesting to note that cpio will still be able to create the directory, but as it does, it will set the permissions to read only, so it won't be able to create any files below that directory.

However, if you remember to use -depth, find will instead start its search at the lowest level, meaning it will list the contents of directories before it lists the directories themselves. This means that the files will already have been replicated by cpio before it sets the read-only permissions on the parent directory.

What if I don't want to replicate my entire home directory, just portions of it? This is where the -prune switch comes into play. Let's say I want to back up everything in my home directory except my tmp directory. I could do this:

find . -type d -name tmp -prune -o -print | cpio -dump /backup

You'll note that the syntax seems a little bit backwards. I used the -name switch to find any directories (-type d) named tmp and pass that list to -prune. I then used the logical or -o so that everything else will be printed and piped to cpio.

I hope the examples provided in the last two articles have helped you to become more comfortable with the find command and its syntax. In the next article, I'd like to continue with the cpio command and compare its usage to the tar command.

Dru Lavigne is a network and systems administrator, IT instructor, author and international speaker. She has over a decade of experience administering and teaching Netware, Microsoft, Cisco, Checkpoint, SCO, Solaris, Linux, and BSD systems. A prolific author, she pens the popular FreeBSD Basics column for O'Reilly and is author of BSD Hacks and The Best of FreeBSD Basics.

Read more FreeBSD Basics columns.

Return to the BSD DevCenter.

Sponsored by: