One-liners illustrating the use of the find command abound on the world wide web. The command’s operation is straight forward, but it has so many options that the man page always makes for fascinating reading. The find command is your friend whenever you need to *find* files based on name, size, file type, creation/access/modification time, ownership, and execute operations on them. Since these are GNU/Linux ABC’s, options and behavior refer to GNU find. YMMV on other flavors of Unix which can be stocked with commands possessing slightly less intuitive defaults.
Anatomy of a find command
Using the example of automating the process of finding unwanted core files and removing them, we’ll build a command line from the ground up.
[usr-4@srv-4 usr-4]$ find -name core ./core ./other/code/ad/projects/monster/core ./.mozilla/core |
With no arguments, find recursively lists all files from our current working directory on down. This command, “find -name core” recursively lists all files named “core” from our current working directory on down. It even prints them by default, unlike back when I was cutting my teeth. Why, in those days, you had to use the -print flag. The important thing was that I had an onion on my belt, which was the style at the time… so let’s add a search path:
[usr-4@srv-4 usr-4]$ find /home/usr-4 -name core /home/usr-4/.mozilla/core /home/usr-4/core /home/usr-4/other/code/ad/projects/monster/core |
Doesn’t change output but will make this command more useful when we run it as a script or cron job. What if I only want to find files in the top few levels of this directory tree, where true core dump files are more likely to live?
[usr-4@srv-4 usr-4]$ find /home/usr-4 -name core -maxdepth 2 /home/usr-4/.mozilla/core /home/usr-4/core |
What if I only want to remove big ones, and not bother with the little guys?
[usr-4@srv-4 usr-4]$ find /home/usr-4 -name core -size +10000k [usr-4@srv-4 usr-4]$ |
I guess none of them are bigger than 10 K. Let’s remove them anyway. But I don’t want to remove my core file way down in my projects subdirectory because I’m saving that one for further crash analysis. Maybe I’ll only remove core files that were modified within the last 24 hours.
[usr-4@srv-4 usr-4]$ find /home/usr-4 -name core -mtime -1 -exec rm {} \; |
Now you see, we get no output from this, which is ok, but if you want to see what was removed throw a print flag in there, like back in the day.
[usr-4@srv-4 usr-4]$ find /home/usr-4 -name core -mtime -1 -print -exec rm {} \; /home/usr-4/.mozilla/core /home/usr-4/core |
The construction of the -exec clause looks weird but is straight-forward.
-exec command {} \; | || | | denotes end of arguments to the command | escape, keeps semicolon from being interpreted by shell | instead of being passed to find. replaced by the current file name being processed |
So there you have it. Dislike the finality of exec? You can do it like this:
[usr-4@srv-4 usr-4]$ find /home/usr-4 -name core -mtime -1 -print -ok rm {} \; /home/usr-4/.mozilla/core < rm ... /home/usr-4/.mozilla/core > ? y /home/usr-4/core < rm ... /home/usr-4/core > ? y |
Some one liners you might enjoy.
Finds new files less than 24 hours old, larger than 2 GB (roughly) and compresses them.
find /backups/sql7backup/tempest/Alerts -size +2000000k -mtime -1 -exec gzip {} \; |
Finds files which do not have correct group writable permissions in a file share and changes them. Notice the bang for negation and the use of the -type option to find directories. If you script this, escape the bang.
find /share ! -perm +g+rw -exec chmod g+rw {} \; find /share -type d ! -perm +g+x -exec chmod g+x {} \; find /share ! -group users -exec chown :users {} \; |
Find also supports combining tests with and/or. Find files owned by a user other than usr-4 or named core. Not that this combination seems particularly useful.
[usr-4@srv-4 usr-4]$ find /home/usr-4 ! -user usr-4 -o -name core /home/usr-4/img/ibmdiskcheck.img /home/usr-4/.mozilla/core /home/usr-4/other/code/ad/projects/monster/core /home/usr-4/projects/DBD/sqsh-2.1/scripts/install.sh /home/usr-4/projects/DBD/sqsh-2.1/scripts/make_wrapper.sh /home/usr-4/projects/DBD/sqsh-2.1/src/Makefile |
One last tip: occassionally the list of files generated by your find command is too long to be processed by -exec. In that case you’ll get an error message. If that happens, try piping to xargs from find, like so:
find /home/usr-4 -name core | xargs rm rm: `/home/usr-4/other/code/ad/projects/monster/core' is a directory |
Oops! I guess we should have specified files of type “f”. Read the man page for lots more fun with find. I trust you’ll find this command delivers everything you’re looking for.