Finding Things in Unix
Pages: 1, 2
Brave enough to try something even more useful but complicated-looking?
Let's get find to not only find this file, but move it to the correct
directory using the following command:
find . -name "*.pdf" -print | grep -v "^\./pdfs/" | xargs -J X mv X ./pdfs/
To see if it worked, let's repeat the original find command:
find . -name "*.pdf" -print
./pdfs/50130201a.pdf
./pdfs/50130201b.pdf
./pdfs/50130201c.pdf
./pdfs/IWARLab.pdf
./pdfs/DoS_trends.pdf
./pdfs/Firewall-Guide.pdf
./pdfs/2000_ports.pdf
So it worked. Let's see why. Once grep finished filtering the find
output, we piped that result to the xargs command to finish the job for
us. The J switch tells xargs to take all of the files it receives and
assume that the file you specify with the command is to be the destination.
For example, before I ran the find command, I had no idea how many files
needed to be moved. There may have been one, or there may have been several. I
needed to let xargs know that regardless of how many files were found, I
want them all moved and I want them all moved to the pdfs directory. That bit
of magic is the job of the J switch. To get the J switch to work
properly, I also defined a character (X) and put that character on either side
of the mv command.
|
Related Reading Learning the Unix Operating System |
Remember that Unix filenames don't necessarily have extensions, so you may want to search for a more complicated pattern. Let's say I want to find any files that have "bsd" somewhere in their name. I would do this command:
find . -name "*bsd*" -print
./.kde/share/icons/favicons/www.freebsd.org.png
./.kde/share/icons/favicons/www.freebsddiary.org.png
./.kde/share/wallpapers/bsdbg1280x1024.jpg
./mnwclient-1.11/contrib/freebsd
We can also find a file by more than just its name. For example, to find
all the files that you have not read in more than (+) 30 days:
find . -atime +30 -print
To see files you haven't modified, use -mtime instead, and to see files you haven't changed the owner or permissions of, use -ctime. The number
after the + indicates how many days or 24-hour periods. To see which
files were modified today, try:
find . -mtime -1 -print
This will show what files were modified during the last 24 hours. Note
that this time you should use the -, as you want to find the files from
less than one day ago.
The other switch that deals with time is the -newer switch. The three
time switches all use 24-hour periods. If you would like to be a bit
more granular in your time than that, the -newer switch will compare a
file's access, modification, and change times to within a minute. For
example, to see if any of your "dot" files were changed since you last
changed your .cshrc file, you could execute this command:
find . -type f -name ".*" -newer .cshrc -print
You'll note that I've included some other new switches in this command. I
specified a "type" of -f for files, as I don't want to see any
directories, just files. I told the -name switch that I was
interested in seeing files that start with a ".". Finally, I used the
-newer switch to indicate that I was interested in the files that were
modified since I last modified my .cshrc file.
Since I've started to combine switches that indicate which files I'm
interested in finding, I should mention that all switches are logically
"anded" unless you use the -o or logical "or". Since the switches are
logically anded, I really told the find utility that I was only
interested in files that were of a certain type and had a certain name
and were newer than my .cshrc file.
Let's look at an example that shows the difference between a logical "and" and a logical "or". If I wanted to see all of the files in my home directory that had not been accessed in the last seven days "and" are larger than 10 Mb, I would use this command:
find . -atime +7 -size +20480 -print
However, if I wanted to see any files that either had not been accessed in the last seven days "or" that were over 10 MB in size, I would use this command instead:
find . -atime +7 -o -size +20480 -print
You'll note that I had to do some math to come up with the number to give
to the -size expression, since -size is looking for the number of 512-byte blocks. However, I could have used the expr command to do the math
for me, like so:
find . -atime +7 -o -size +`expr 10 \* 1024 \* 2` -print
Note that in this example, everything between the backquotes (the ` on the far left of your
keyboard) is what will do the required math. We still need
the + in front of the first back quote, as we want to see files greater than
10 MB. You could also test what the results of the math will be by adding the
echo command to the beginning of the command:
echo find . -atime +7 -o -size +`expr 10 \* 1024 \* 2` -print
find . -atime +7 -size +20480 -print
It is a good idea to echo complex commands first, to ensure that the
stuff you've quoted will do what you expect before asking the find command to execute it.
That should get you started for this week. In next week's article, I'll
continue through the rest of the expressions and give some more practical
examples for using the find 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.
