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.
Try the following:
-exec ... +
, passes (typically) all matching paths to the specified command, which is them most efficient approach.Both
chmod
andxattr
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 tosh -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).