Why doesn't find's "{}" symbol do what I want?

Why doesn't find's "{}" symbol do what I want?

"find" has a -exec option that will execute a particular command
on all the selected files. Find will replace any "{}" it sees
with the name of the file currently under consideration.

So, some day you might try to use "find" to run a command on
every file, one directory at a time. You might try this:

find /path -type d -exec command {}/\* \;

hoping that find will execute, in turn

command directory1/*
command directory2/*
...

Unfortunately, find only expands the "{}" token when it appears
by itself. Find will leave anything else like "{}/*" alone, so
instead of doing what you want, it will do

command {}/*
command {}/*
...

once for each directory. This might be a bug, it might be a
feature, but we're stuck with the current behaviour.

So how do you get around this? One way would be to write a
trivial little shell script, let's say "./doit", that consists of

command "$1"/*

You could then use

find /path -type d -exec ./doit {} \;

Or if you want to avoid the "./doit" shell script, you can use

find /path -type d -exec sh -c 'command $0/*' {} \;

(This works because within the 'command' of "sh -c 'command' A B C ...",
$0 expands to A, $1 to B, and so on.)

or you can use the construct-a-command-with-sed trick

find /path -type d -print | sed 's:.*:command &/*:' | sh

If all you're trying to do is cut down on the number of times
that "command" is executed, you should see if your system has the
"xargs" command. Xargs reads arguments one line at a time from
the standard input and assembles as many of them as will fit into
one command line. You could use

find /path -print | xargs command

which would result in one or more executions of

command file1 file2 file3 file4 dir1/file1 dir1/file2

Unfortunately this is not a perfectly robust or secure solution.
Xargs expects its input lines to be terminated with newlines, so
it will be confused by files with odd characters such as newlines
in their names.



Home FAQ