Skip to main content
replaced http://unix.stackexchange.com/ with https://unix.stackexchange.com/
Source Link

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?Why does my shell script choke on whitespace or other special characters?

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?

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?

Source Link
Gilles 'SO- stop being evil'
  • 865.3k
  • 205
  • 1.8k
  • 2.3k

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?