Running Commands on What You Find (Unix Power Tools, 3rd Edition)
9.9. Running Commands on What You Find
Often, when you find a file, you
don't just want to see its name; you want to do
something, like grep (Section 13.2) for a text string. To do this, use the
-exec operator. This allows you
to specify a command that is executed upon each file that is found.
The syntax is peculiar and in many cases, it is simpler just to pipe
the output of find to xargs (Section 28.17). However,
there are cases where -exec is just the thing,
so let's plunge in and explain its peculiarities.
The -exec operator
allows you to execute any command, including another
find command. If you consider that for a moment,
you realize that find needs some way to
distinguish the command it's executing from its own
arguments. The obvious choice is to use the same end-of-command
character as the shell (the semicolon). But since the shell uses the
semicolon itself, it is necessary to escape the character with a
backslash or quotes.
Therefore, every -exec operator ends with the
characters \;. There is one more special argument
that find treats differently:
{}.
These two characters are used as the variable whose name is the file
find found. Don't bother
rereading that last line: an example will clarify the usage. The
following is a trivial case and uses the -exec
operator with echo to mimic the
-print operator:
% find . -exec echo {} \;
The C shell (Section 29.1) uses
the characters { and }, but
doesn't change {} together, which
is why it is not necessary to quote these characters. The semicolon
must be quoted, however. Quotes can be used instead of a
backslash:
% find . -exec echo {} ';'
as both will sneak the semicolon past the shell and get it to the
find command. As I said before,
find can even call find. If
you wanted to list every symbolic link in every directory owned
by a group staff under the current directory,
you could execute:
% find `pwd` -type d -group staff -exec find {} -type l -print \;
To search for all files with
group-write permission under
the current directory and to remove the permission, you can use:
% find . -perm -20 -exec chmod g-w {} \;
or:
% find . -perm -20 -print | xargs chmod g-w
The difference between
-exec and xargs is subtle.
The first one will execute the program once per file, while
xargs can handle several files with each
process. However, xargs may have problems with
filenames that contain embedded spaces. (Versions of
xargs
that support the -0 option can avoid this
problem; they expect NUL characters as delimiters instead of
spaces, and find's
-print0 option generates output that way.)
Occasionally, people create a strange file
that they can't delete. This could be caused by
accidentally creating a file with a space or some control character
in the name. find and -exec
can delete this file, while xargs could not. In
this case, use ls -il to list
the files and i-numbers, and use the
-inum
operator with -exec to delete the file:
% find . -inum 31246 -exec rm {} ';'
If you wish, you can use
-ok, which does the same as
-exec, except the program asks you to confirm
the action first before executing the command. It is a good idea to
be cautious when using find, because the program
can make a mistake into a disaster. When in doubt, use
echo as the command. Or send the output to a
file, and examine the file before using it as input to
xargs. This is how I discovered that
find requires {} to stand
alone in the arguments to -exec. I wanted to
rename some files using -exec mv {} {}.orig, but
find wouldn't replace the
{} in {}.orig. I learned that I
have to write a shell script that I tell find to
execute.
NOTE:
GNU find will replace
the {} in {}.orig for you. If
you don't have GNU find, a little
Bourne shell while loop with redirected input can
handle that too:
$ find ... -print |
> while read file
> do mv "$file" "$file.orig"
> done
find writes the filenames to its standard output.
The while loop and its read
command read the filenames from standard input then make them
available as $file, one by one.
Section 9.12 and Section 9.27 have more examples of
-exec.
-- BB
9.8. Exact File-Time Comparisons9.10. Using -exec to Create Custom Tests
Copyright © 2003 O'Reilly & Associates. All rights reserved.
Wyszukiwarka
Podobne podstrony:
ch09BW ch09ch09ch09CH09 (10)ch09ch09 (4)ch09ch09ch09ch09ch09ch09ch09ch09ch09więcej podobnych podstron