I have the following two scripts:
#script1.sh:
#!/bin/bash
this_chunk=(1 2 3 4)
printf "%s\n" "${this_chunk[@]}" | ./script2.sh
#script2.sh:
#!/bin/bash
while read -r arr
do
echo "--$arr"
done
When I execute script1.sh
, the output is as expected:
--1
--2
--3
--4
which shows that I was able to pipe the elements of the array this_chunk
as arguments to script2.sh
. However, if I change the line calling script2.sh
to
printf "%s\n" "${this_chunk[@]}" | xargs ./script2.sh
there is no output. My question is, how to pass the array this_chunk
using xargs
, rather than simple piping? The reason is that I will have to deal with large arrays and thus long argument lists which will be a problem with piping.
Edit: Based on the answers and comments, this is the correct way to do it:
#script1.sh
#!/bin/bash
this_chunk=(1 2 3 4)
printf "%s\0" "${this_chunk[@]}" | xargs -0 ./script2.sh
#script2.sh
#!/bin/bash
for i in "${@}"; do
echo $i
done
CodePudding user response:
how to pass the array this_chunk using xargs
Note that xargs
by default interprets '
"
and \
sequences. To disable the interpretation, either preprocess the data, or better use GNU xargs with -d '\n'
option. -d
option is not part of POSIX xargs.
printf "%s\n" "${this_chunk[@]}" | xargs -d '\n' ./script2.sh
That said, with GNU xargs prefer zero terminated streams, to preserve newlines:
printf "%s\0" "${this_chunk[@]}" | xargs -0 ./script2.sh
Your script ./script2.sh
ignores command line arguments, and your xargs
spawns the process with standard input closed. Because the input is closed, read -r arr
fails, so your scripts does not print anything, as expected. (Note that in POSIX xargs, when the spawned process tries to read from stdin, the result is unspecified.)