I intend to get a comma separated list of files and then pass it as argument to a command using xargs.
However it seems xargs ignores the part of command after &&.
$ find */build* -printf '%h/%f,'
jenkins/build.jenkinsfile,jenkins/build-x.groovy,
$ find */build* -printf '%h/%f,' | xargs -t python3 -m coverage combine python-bridge && python3 -m coverage xml --omit
python3 -m coverage combine python-bridge jenkins/build.jenkinsfile,jenkins/build-x.groovy,
Couldn't combine from non-existent path 'jenkins/build.jenkinsfile,jenkins/build-x.groovy,'
So, the command is interpreted as:
python3 -m coverage combine python-bridge jenkins/build.jenkinsfile,jenkins/build-x.groovy,
Expected:
python3 -m coverage combine python-bridge && python3 -m coverage xml --omit jenkins/build.jenkinsfile,jenkins/build-x.groovy,
Any pointer will be a great help.
CodePudding user response:
Meta: I wrote a much longer comment that Stack seems to have discarded somehow, so I am re-doing as an answer to get edit history even though I'm not sure this is really programming (and thus may need to be deleted).
It's not xargs. The shell breaks that input into two commands, and then executes the first pipeline by running find */build* -printf '%h/%f,'
as one process with stdout connected to a pipe and xargs -t python3 -m coverage combine python-bridge
as another process with stdin connected to that same pipe; only after both of these complete, and only if the xargs
is successful which in turn is only if the python3 -m ...
is successful which it wasn't, the shell would run the second command python3 -m coverage xml --omit
as a third process.
You could pass the &&
to xargs
by quoting it: any of '&&' "&&" \&\&
. However xargs
is not a shell and will not interpret the &&
as an 'and' operator; it will run one python3
process with arguments -m coverage combine python-bridge && python3 -m coverage xml --omit
with the (one) input 'filename' jenkins/build.jenkinsfile,jenkins/build-x.groovy,
appended, and that won't work either.
You can have xargs
run a shell which in turn runs the commands you want:
find */build* -printf '%h/%f,' |
xargs -t sh -c 'python3 -m coverage combine python-bridge && python3 -m coverage xml --omit $*' dummy0'
# in general you should use "$@" to prevent split glob from mangling 'special' arguments
# but here they have already survived xargs default parsing so shouldn't be special
But much simpler is to arrange your commands more appropriately:
python3 -m coverage combine python-bridge &&
find */build* -printf '%h/%f,' | python3 -m coverage xml --omit
or since this works correctly only if the list of files fits in one command so you don't actually want xargs
main functionality, just
python3 -m coverage combine python-bridge &&
python3 -m coverage xml --omit $(find */build* -printf '%h/%f,')