Running multiple commands with xargs
cat a.txt | xargs -I % echo %
In the example above, xargs takes echo %
as the command argument. But in some cases, I need multiple commands to process the argument instead of one. For example:
cat a.txt | xargs -I % {command1; command2; ... }
But xargs doesn't accept this form. One solution I know is that I can define a function to wrap the commands, but I want to avoid that because it is complex. Is there a better solution?
cat a.txt | xargs -d $'\n' sh -c 'for arg do command1 "$arg"; command2 "$arg"; ...; done' _
...or, without a Useless Use Of cat:
<a.txt xargs -d $'\n' sh -c 'for arg do command1 "$arg"; command2 "$arg"; ...; done' _
To explain some of the finer points:
The use of
"$arg"
instead of%
(and the absence of-I
in thexargs
command line) is for security reasons: Passing data onsh
's command-line argument list instead of substituting it into code prevents content that data might contain (such as$(rm -rf ~)
, to take a particularly malicious example) from being executed as code.Similarly, the use of
-d $'\n'
is a GNU extension which causesxargs
to treat each line of the input file as a separate data item. Either this or-0
(which expects NULs instead of newlines) is necessary to prevent xargs from trying to apply shell-like (but not quite shell-compatible) parsing to the stream it reads. (If you don't have GNU xargs, you can usetr '\n' '\0' <a.txt | xargs -0 ...
to get line-oriented reading without-d
).The
_
is a placeholder for$0
, such that other data values added byxargs
become$1
and onward, which happens to be the default set of values afor
loop iterates over.
You can use
cat file.txt | xargs -i sh -c 'command {} | command2 {} && command3 {}'
{} = variable for each line on the text file