1

I do not generally use Solaris, but today I need to craft a find command to execute an operation on identified files using the shell. I am finding that the {} characters are not getting substituted and cannot find an alternative.

For example:

 bash-3.2# find / -exec sh -c "echo {}" \;

This causes it to print {} for each file instead of the file name.

  • Try removing the quotes. – user156990 Mar 21 '16 at 18:05
1

As written in the man page and in the standard, {} must be in a separate argument.

find / -exec sh -c 'echo $1' dummy '{}' \;

works as expected.

  • 1
    And this is the link to the said standard: If a utility_name or argument string contains the two characters "{}", but not just the two characters "{}", it is implementation-defined whether find replaces those two characters or uses the string without change. It seems GNU find replaces "{}" characters that are combined with other characters, Solaris find does not. – Andrew Henle Mar 21 '16 at 20:45
  • gfind does not behave orthogonal, gfind . -exec echo "aaa {}" \; works as expected, but gfind . -exec echo "aaa {}" + behaves as if gfind . -exec echo "{}" + was called. – schily Mar 22 '16 at 17:37
  • Well, IEEE 1003.1 doesn't mandate that an implementation's definition must be consistent... – Andrew Henle Mar 22 '16 at 20:27
1

The only standard way to use find -exec … is to pass {} as a separate argument. The behavior when an argument contains {} is not standardized. It seems that you're used to the GNU behavior where {} is substituted in a substring. The find command on Solaris only substitutes {} when an argument consists only of {}.

The GNU behavior is not particularly useful, and sometimes annoying, because substituting a file name inside an argument is brittle. Unless you have known constraints on the file names, there's no way to know where a file name starts and ends. For example, with GNU find, find / -exec sh -c "echo {}" \; does not print the file names in general. It only prints the file names when they don't contain any shell special character. If you run it in a directory containing a file called ;rm -r ~, say goodbye to your files.

The reliable (and portable) way to call a shell from find -exec is to pass the file names as an argument to the shell.

find … -exec sh -c 'echo "$0"' {} \;

In most cases you can pass arguments in batches and iterate over the arguments in the shell. It's somewhat faster. Note that the very first argument after the shell code is $0 which is not includes in "$@".

find … -exec sh -c 'for x; do echo "$x"; done' _ {} +

See also Why does my shell script choke on whitespace or other special characters?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.