parallel
runs a shell (which exact one depending on the context in which it is called, generally, when called from a shell, it's that same shell) to parse the concatenation of the arguments.
So:
parallel debug-call 'a b' {} ::: 'a b' c
is the same as
parallel 'debug-call a b {}' ::: 'a b' c
parallel
will call:
your-shell -c 'debug-call a b <something>'
Where <something>
is the arguments (hopefully) properly quoted for that shell. For instance, if that shell is bash
, it will run
bash -c 'debug-call a b a\ b'
Here, you want:
parallel 'debug-call "a b" {}' ::: 'a b' c
Or
parallel -q debug-call 'a b' {} ::: 'a b' c
Where parallel
will quote the arguments (in the correct (hopefully) syntax for the shell) before concatenating.
To avoid calling a shell in the first place, you could use GNU xargs
instead:
xargs -n1 -r0 -P4 -a <(printf '%s\0' 'a b' c) debug-call 'a b'
That won't invoke a shell (nor any of the many commands ran by parallel
upon initialisation), but you won't benefit from any of the extra features of parallel
, like output reordering with -k
.
You may find other approaches at Background execution in parallel
Best Answer
parallel
runs the command in a shell already (which shell it is is determined byparallel
using heuristics (the intention being to invoke the same shell as the oneparallel
was invoked from). You can set the$PARALLEL_SHELL
variable to fix the shell).It's not a command you're passing to
parallel
like you would for theenv
orxargs
command, but a shell command line (like you would for theeval
command).Like for
eval
, inparallel arg1 arg2
,parallel
is concatenating those arguments with spaces in between (so it becomesarg1 arg2
) and that string is passed to<the-shell> -c
.For the arguments that are passed on
parallel
's stdin,parallel
quotes them in the format expected by that particular shell (a difficult and error prone task which is why you'll find there have been a lot of bugs fixed around that inparallel
's Changelog (some are still not fixed as of 2017-03-06)) and appends it to that command line.So for instance, if called from within
bash
,Would have parallel call
bash -c
withecho foo foo\'bar
as the command line. And if called from withinrc
(or withPARALLEL_SHELL=rc
)rc -c
withecho foo foo''''bar
.In your:
parallel
concatenates those arguments which gives:And with the
{}
expanded and quoted in the right format for the shell you're callingparallel
from, passes that to<that-shell> -c
which will callbash -c echo
with:$1
in$0
and the current argument in$1
.It's not how
parallel
works. Here, you'd probably want:To see what
parallel
does, you can run it understrace -fe execve
(or the equivalent on your system if not Linux).Here, you could use GNU
xargs
instead ofparallel
to get a simpler processing closer to what you're expecting:See also the discussion at https://lists.gnu.org/archive/html/bug-parallel/2015-05/msg00005.html
Note that in
bash -c 'echo foo' '' foo
, you're making$0
the empty string for that inline-script. I would avoid that as that$0
is also used in error messages. Compare:with.
Also note that leaving variables unquoted has a very special meaning in
bash
and thatecho
can generally not be used for arbitrary data.