Sams Teach Yourself Shell Programming in 24 Hours
(Publisher: Macmillan Computer Publishing)
Author(s): Sriranga Veeraraghavan
ISBN: 0672314819
Publication Date: 01/01/99

Previous Table of Contents Next


find: Combining Options

If you specify more than one option, the file must match all options to be displayed:

find / -name alpha -size +50 -mtime -3 -print

Here find displays files only when all the following are true:

  The name is alpha
  The size is greater than 50 blocks
  The file was last modified fewer than 3 days ago

You can specify a logical “or” condition using -o:

find / \( -size +50 -o -mtime -3 \) -print

Notice the use of the escaped parentheses to group the “either” and “or” options. This finds files that either have size greater than 50 blocks or were last modified fewer than 3 days ago.

find: Negating Options

You can use the ! sign to select files that do not match the given option:

find /dev ! \( -type b -o -type c -o type d \) -print

This locates all files in the /dev directory and its subdirectories that are not block special device files, character special device files, or directories. This is a useful command to locate device names that users have misspelled, which leaves a regular file in /dev that can waste a large amount of disk space.

find: -print Action

-print is an action that tells find to display the pathnames of all files that match the options given before -print. If you put the -print action before other options in the command line, those options are not used in the selection process:

find / -size -20 -print -mtime +30

This command prints all files that contain fewer than 20 blocks. The -mtime option is ignored because it comes after the -print action on the command line.

If no action is specified on the command line, -print is usually done by default. On older versions of UNIX, however, you must remember to include -print specifically, or no output is generated.

find: -exec Action

-exec is an action that lets you specify a UNIX command to run on each of the files that match the options given:

find / -name alpha -exec chmod a+r {} \;

Following -exec, you should specify a complete UNIX command and put {} where the filename will be inserted. Add \; at the end of the command to complete the required syntax. In the previous example, chmod runs on every file named alpha so that everyone can read the file.

find / -name core -exec rm -f {} \;

This example finds all files on the system named core and executes the rm command to delete them. The -f option to rm is specified so that rm does not ask for confirmation if you don’t own the file and don’t have write permission to the file. This is a useful command for root to run periodically because, if a process aborts, it might leave a debugging file named core in the current directory. After a while, these core files, which are not small, can collectively consume an unreasonable amount of disk space. This find command restores that disk space by finding and deleting those core files.


Note:  
If you have thousands of files to process, xargs (covered in the next section) is more efficient than -exec. For example,
find / -name core -print | xargs rm -f

This command also deletes all core files much more quickly and with less overhead than the -exec option, which calls rm once for each file.


xargs

xargs is a command that accepts a list of words from standard input and provides those words as arguments to a given command:

cat filelist | xargs rm

You cannot pipe the output of cat directly to rm because rm does not look for filenames on standard input. xargs reads the files being passed by cat and builds up a command line beginning with rm and ending with the filenames. If there are a large number of files, xargs runs the rm command multiple times, deleting some of the files each time. You can specify how many arguments from standard input to build up on the command line with the -n option:

cat filelist | xargs -n 20 rm

-n 20 says to put only 20 arguments on each command line, so you delete only 20 files at a time. Here is a different example to give you more insight into how xargs works:

$ ls
acme
report16
report3
report34
report527
$ ls | xargs -n 2 echo ===
=== acme report16
=== report3 report34
=== report527
$

The first ls command shows us that there are only five files in the current directory. (These five can be regular files or directories; it does not matter for this example.) Next you pipe the output of ls to xargs, which composes and executes this command (the first of several):

echo === acme report16

The command begins with echo === because these are the arguments given to the xargs command. The command then contains two filenames read from standard input. -n 2 tells xargs to add only two words from standard input to each echo command. I added === as the first echo argument so you can visually find the output from each separate echo command. You can see that xargs called echo three times to process all the standard input.

xargs can be used to solve this problem:

$ rm abc*
rm: arg list too long

The current directory contained too many filenames starting with abc, and the command buffer overflowed, so an error message was printed, and none of the files were deleted. xargs can solve this buffer overflow problem:

ls | grep '^abc' | xargs -n 20 rm

Here you use grep (covered in Chapter 15, “Text Filters”) and regular expressions (covered in Chapter 16, “Filtering Text Using Regular Expressions”) to filter the output of ls passing only filenames that begin with abc. xargs allows rm to operate on those files and delete them, no matter how many there are.


Previous Table of Contents Next