How to ignore xargs commands if stdin input is empty?
In terms of xargs
, you can use -r
as suggested, however it's not supported by BSD xargs
.
So as workaround you may pass some extra temporary file, for example:
find /mydir -type f -name "*.txt" -print0 | xargs -0 chown root $(mktemp)
or redirect its stderr into null (2> /dev/null
), e.g.
find /mydir -type f -name "*.txt" -print0 | xargs -0 chown root 2> /dev/null || true
Another better approach is to iterate over found files using while
loop:
find /mydir -type f -name "*.txt" -print0 | while IFS= read -r -d '' file; do
chown -v root "$file"
done
See also: Ignore empty results for xargs in Mac OS X
Also please note that your method of changing the permissions isn't great and it's discouraged. Definitely you shouldn't parse output of ls
command (see: Why you shouldn't parse the output of ls). Especially when you're running your command by root, because your files can consist special characters which may be interpreted by the shell or imagine the file having a space character around /
, then the results can be terrible.
Therefore you should change your approach and use find
command instead, e.g.
find /mydir -type f -name "*.txt" -execdir chown root {} ';'
Users of non-GNU xargs may take advantage of -L <#lines>
, -n <#args>
, -i
, and -I <string>
:
ls /empty_dir/ | xargs -n10 chown root # chown executed every 10 args or fewer
ls /empty_dir/ | xargs -L10 chown root # chown executed every 10 lines or fewer
ls /empty_dir/ | xargs -i cp {} {}.bak # every {} is replaced with the args from one input line
ls /empty_dir/ | xargs -I ARG cp ARG ARG.bak # like -i, with a user-specified placeholder
Keep in mind that xargs splits the line at whitespace but quoting and escaping are available; RTFM for details.
Also, as Doron Behar mentions, this workaround isn't portable so checks may be needed:
$ uname -is
SunOS sun4v
$ xargs -n1 echo blah < /dev/null
$ uname -is
Linux x86_64
$ xargs --version | head -1
xargs (GNU findutils) 4.7.0-git
$ xargs -n1 echo blah < /dev/null
blah
For GNU xargs
, you can use the -r
or --no-run-if-empty
option:
--no-run-if-empty
-r
If the standard input does not contain any nonblanks, do not run the command. Normally, the command is run once even if there is no input. This option is a GNU extension.
The BSD version of xargs
, which is used on macOS, does not run the command for an empty input, so the -r
option is not needed (nor is it accepted by that version of xargs
).
man xargs
says --no-run-if-empty
.