Multiple commands with find and xargs, also accounting for special characters

1k views Asked by At

In OS X I am trying to combine the following two commands into a single command in a bash script, so that find operates once only. The files used by find contain spaces and special characters.

Command 1:

find /path -print0 | tr '\n' '\0' | xargs -0 chmod -N

Command 2:

find /path -print0 | tr '\n' '\0' | xargs -0 xattr -c

Both the above commands work.

I understand from 'Make xargs execute the command once for each line of input' that multiple commands can be executed through xargs with something like

find /path -print0 | xargs -0 -I '{}' sh -c 'command1 {} ; command2 {}'

However, my attempt to combine the commands with

find /path -print0 | tr '\n' '\0' | xargs -0 -I '{}' sh -c 'chmod -N {} ; xattr -c {}'

results in multiple errors for each file and folder in the /path, such as

chmod: Failed to clear ACL on file {}: No such file or directory
xattr: No such file: {}
sh: -c: line 0: syntax error near unexpected token `('

Is anyone able to help? Thank you in advance.

1

There are 1 answers

2
mklement0 On

Try the following:

find /path -exec sh -c 'chmod -N "$@"; xattr -c "$@"' - {} +
  • -exec ... +, passes (typically) all matching paths to the specified command, which is them most efficient approach.

    • Both chmod and xattr support multiple file operands, so this approach is feasible.

    • find properly retains argument boundaries when passing substituting the paths for {}, so it would even handle filenames with embedded newlines correctly.
      Incidentally: I'm unclear on what the purpose of tr '\n', '\0' in your code is, given that you already output \0-separated paths thanks to -print0.

  • Note the - as the first (dummy) argument passed to sh -c, because the first argument will become $0.


As for the problem with your original command:

I can't explain the specific symptoms, but one problem is that you're not quoting the {} instances inside your shell command, which makes them subject to word splitting (breaks file paths with embedded spaces into multiple arguments).