[Often, when you find a file, you don't just want to see its name; you want to do something, like grep 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. -TOR ]
The syntax is peculiar and in many cases, it is simpler just to pipe the output of find to xargs ( 17.2 ) . 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 (i.e., the semicolon). Since the shell uses the semicolon ( 8.5 ) 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
(
8.6
)
to mimic the
-print
operator:
%find . -exec echo {} \;
The C shell uses the characters
{
and
}
(
9.5
)
, 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 , you could execute:
`...` |
%
|
---|
To search for all files with group-write permission and remove the permission, you can use:
-perm |
%
|
---|
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 ( 9.22 ) with filenames that contain embedded spaces.
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 ( 1.22 ) , and use the -inum operator with -exec ( 23.16 ) 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 first to confirm the action 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 the file 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 (
17.11
)
that I tell
find
to execute. [A little Bourne shell
while
loop (
44.10
)
with
redirected input (
45.23
)
can handle that too:
> |
$ |
---|
find
writes the filenames to its standard output. The
while
loop and its
read
command (
44.13
)
read the filenames from standard input, then make them available as
$file
, one by one.
-JP
]
Articles 17.12 and 17.24 have more examples of -exec .
-