Unix: Making better use of the find command

The find command is one of the most basic Unix commands, but that doesn't mean you're making good use of its many features.

Just because a Unix command is one those most of us learn within the first few hours of our exposure to a Unix/Linux OS doesn't mean we have grasped the many ways in which it can be used to make our systems administration work easier. The find command is extremely versatile and can locate files on more criteria than many of us may realize. We can also make use of the find command for other tasks than just locating files. For example, for removing, moving, or changing files in some way. The most obvious use of the find command is to find files by name.

$ find . -name tryme*
./bin/tryme5
./bin/tryme
./py/tryme1.py
./py/tryme2.py
./.fetch/tryme2
Putting -print at the end of your find commands is optional. But use -print0 if, for some reason, you want all the found files to be listed on a single line with no spaces between them.
$ find . -name tryme* -print0
./bin/tryme5./bin/tryme./py/tryme1.py./py/tryme2.py./.fetch/tryme2
Did you know that there's also an option that allows you to search by name independent of the case in which those file names are expressed? Try -iname instead of -name and you can do just that.
$ find . -iname tryme*
./bin/tryme5
./bin/tryme
./bin/TRYME
./py/tryme1.py
./py/tryme2.py
./.fetch/tryme2
You can also use the find command to locate files by their owners or by the groups associated with those files.
# find / -type f -user bguy
# find / -group admins
# find / -gid 99
$ find -user shs
Notice how the starting point is also optional (see the fourth command above). The find command will start its search in the local directory if no start point is provided. Maybe you want to locate all of the symbolic links within your home directory and see what they point to (as opposed to what those directories contain)? No problem, try this:
$ find . -type l | xargs ls -ld
lrwxrwxrwx 1 shs staff 5 Dec  7 18:36 ./scripts -> ./bin
lrwxrwxrwx 1 shs staff 4 Nov 23 15:27 ./tmp -> /tmp
If we'd just run find . -type l in the above command, we'd be viewing the files in /tmp and the local bin directory. Or maybe we just want the names of the links to be listed and not what they point to. If so, you could do this:
$ find . -type l -print | xargs ls -ld | awk '{print $9}'
./scripts
./tmp
But, of course, all we really need is this:
$ find . -type l -print
./scripts
./tmp
If you want to find files by type, but only want to look in top level directories, not directories, subdirectories, third level directories, etc., you can limit how far your find command will dig through your files by setting a -maxdepth limit:
$ find . -maxdepth 1 -type d
Change the 1 to a 2 if you want to search directories and subdirectories, but not go any further. We can also look for files based on their ages or their size. Here's a command that will only list files that contain between 1,000 and 10,000 characters.
$ find . -size +1000c -size -10000c -print
Here's one that will list files larger 10,000 characters:
$ find . -size +10000c
And, as you might already know, it's no longer necessary to tack -print on to the end of your find command. That's the default action and the find command will assume this when you don't specify some other action. You can also use the find command to locate files with specific permissions. Not many files will require 777 (giving everyone read, write, and execute access). So, maybe you want to look for them and maybe you want to use the -ls option to show a long listing to confirm those settings.
$ find . -type f -perm 777 -ls
15089878    4 -rwxrwxrwx   1 shs      staff        31 Mar  1 15:22 ./bin/runme
Another good use for find is to find files with the setuid or setgid bit set:
$ find . -perm -4000 -o -perm -2000
./bin/try3
./bin/showday
$ find . -perm -4000 -o -perm -2000 | xargs ls -l
-rwsr-xr-x 1 shs staff  79 Aug 31 15:19 ./bin/showday
-rwsr-sr-x 1 shs staff 100 Jul 11  2010 ./bin/try3
Note that the "000" in the permissions spec does not mean that no other permissions are set. You might especially want to look for files with these settings that are owned by root:
# find / -user root -perm -4000 -o -perm -2000
The find command also allows you to search for files by timestamp. The -mtime (last modification time), -atime (last access time), and -ctime (last status change time) can all be used in find commands. This command will find files that have been changed in the last 10 days:
$ find . -mtime -10 -ls
There are two ways to add an action to the end of a find command. One is to use the -exec option. The other is to pass the output of the find command to xargs for further processing. Both work well. Some admins strongly favor one approach over the other, but I'm impartial. Here's one command to show the top line of any file named "xyz":
$ find . -name xyz -exec head -1 {} \;
hello
Here's another:
$ find . -name xyz | xargs head -1
==> ./xyz <==
hello
You can also use the find command to copy files to particular directories. Say you want to copy a file to every top level directory. You might use a command like this:
$ find . -maxdepth 1 -type d -exec cp .htaccess {} \;
This command says "find every top level directory in the current location and copy the .htaccess file to it". You can use the -newer option to find files that are newer than some particular file. There doesn't seem to a similar option for older.

$ find . -maxdepth 1 -type f -newer newfile

The find command can be extremely useful for detecting and resolving problems on your systems.

Read more of Sandra Henry-Stocker's Unix as a Second Language blog and follow the latest IT news at ITworld, Twitter and Facebook.

Top 10 Hot Internet of Things Startups
Join the discussion
Be the first to comment on this article. Our Commenting Policies