Unix: Finding your files your way

It's easy to find files on Unix systems. You can find them by almost any criteria that you can imagine. The bigger challenge is deciding how to describe what you're looking for and deciding what to do with the files once you find them.

What do you best remember or most know about files when you need to find them and should they be removed, chmod'ed, compressed or edited? The find command gives you more options than most of us will ever use and, combined with exec and xargs commands, can become some of your favorite command line powerhouses. The most obvious option is to search for files by name. You can search for files by their full names or using some portion of the names. If you use .pl extensions on your perl scripts, for example, you can locate all your perl scripts with a command like this:

$ find . -name "*.pl" -ls

If you don't use file extensions, you can serach for scripts by looking for the related shebang line:

$ find . -type f -exec grep "/usr/bin/perl" {} \; -ls

This command will show the shebang line and then the name of the file, but it works

#!/usr/bin/perl -w
12731688    4 -rw-------   1 me       admins       2440 Apr 22  2012 ./chkPass
12763143    4 -rwx------   1 me       admins        374 Jul 13 10:58 ./bin/doit

Another common way to look for files is to search for them by age. Maybe you were working on a script last month and just can't remember what you called it. If you know you created or updated the file within the last couple of weeks, however, you can look for files that have been modified within that time frame. This command will list files modified within the last two weeks.

$ find . -mtime -14 -ls

You can also look for files that have been created or modified since some particular data and time, but this requires an extra command. I like to use commands like these. First, I create a file with a specific time stamp -- 00:00 on Nov 1st (i.e., midnight on Oct 31st) -- and then I look for files that are newer than it.

$ touch -t 11010000 Nov
$ find . -newer Nov -ls

Using touch, you can create a file with any date and time you need. The syntax for touch -t is:

<b>touch -t [[CC]YY]MMDDhhmm[.ss] filename</b>

The CCYY part (i.e., the year) will default to the current year, of course, so spell out 11 or 2011 if you want to begin your search some earlier year -- but be prepared for a possible avalanche of output. A lot of files are added in the span of a year+ and you might just end up refining your search several times before you get something that works for you. You can also use the -newer argument to look for files that are newer than some other file that you expect was created or modified around the same time as the one you happen to be looking for. Want to find files that were modified today? Use find's -mtime option but add -daystart so that it doesn't start its search with yesterday.

$ find . -daystart -mtime -1 -ls

To find files by size, you can specify the minimum number of bytes that a file must have to meet your criteria:

$ find . -size +100000 -ls

If you're doing this as a normal user (not root) and want to avoid seeing errors for all the files you're not allowed to see, just pipe standard error to /dev/null:

$ find /home -size +100000 -ls 2>/dev/null

You can even look for files that aren't associated with a current account. Maybe a former coworker left files outside of his home directory and you want to track them down.

$ find . -nouser -ls

Finding files for a specific user is just as easy.

$ find /tmp -user me -ls

Searching by content can be accomplished by pairing your find command with a grep command like this:

$ find . -type f -exec grep "magic" {} \; -ls
Boldness has genius, power, and magic in it. "
15089905    8 -rwxr-xr-x   1 shs      faculty      4559 Sep  5  2011 ./stash/sayings
echo "What's the magic word?"
until [ "$guess" = $magicword ]
15090080    4 -rwxr-xr-x   1 shs      faculty       171 Oct  6  2010 ./scripts/mword

But, as note earlier, with commands like this, the file name comes after the identified content. You can also do this kind of search with find and xargs.

$ find . -type f | xargs grep "magic"

And, of course, you don't have to stop at just finding files. You can use a mix of find and -exec or find and xargs to remove files you don't want, compress them, move them, etc. Remove those orphaned files:

$ find . -nouser | xargs rm

Compress those large files:

$ find /home -size +100000 -exec bzip2 {} \;

If you want to execute this command only in the current directory and immediate subdirectories, you can add a maxdepth command which will keep your search from descending further.

$ find . -maxdepth 2 -size +100000 -exec bzip2 {} \;

A command like this one will search for .pl files and then use grep -L to identify those that don't contain a "use script" directive.

$ find . -name '*.pl' | xargs grep -L '^use strict'

A command like this one will create a file containing a list of files that start with the word "Lab" but, again, only looks in the current directory and immediate subdirectories.

find . -maxdepth 2 -name 'Lab*' > Labfiles

You can also use find commands to list everything but files that match a certain pattern or patterns.

$ find . -not -name "*.pl"
$ find . -not -name "*.pl" -not -name "*.sh" -not -name "*.py"

Once you've identified find commands that work well for you, don't forget to turn them into aliases so that you can easily reuse them.

alias findbig='find ~ -size +1000000 -ls'
alias findorphans='find / -nouser'
alias rmorphans='find / -nouser -exec rm {}\;'

A good set of find commands, especially if they're been turned into aliases, can help keep you and your files in pretty good shape.

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

Join the Network World communities on Facebook and LinkedIn to comment on topics that are top of mind.
Must read: 10 new UI features coming to Windows 10