Arithmetic with GNU parallel

I want to run some script over powers of two in parallel. Doing so by giving GNU Parallel a list of the powers of two I want works well:

%>parallel echo {} ::: 32, 64, 128, 256, 512, 1024
32
64
128
256
512
1024
%>

I can also give GNU Parallel a range of values without issue:

%>parallel echo {} ::: {5..10}
5
6
7
8
9
10
%>

But once I include the bit of arithmetic in the GNU Parallel command, I am met with a syntax error:

%>parallel echo $((2**{})) ::: {5..10}
bash: 2**{}: syntax error: operand expected (error token is "{}")
%>

This surprises me because I can generate these values in a for loop as so:

%>for N in {5..10}; do echo $((2**N)); done
32
64
128
256
512
1024
%>

What is the way to do this using GNU Parallel? I am not concerned with order.

Asked By: Will

||

You need to quote the entire command being run by parallel, for example:

$ parallel 'echo $((2**{}))' ::: {5..10}
32
64
128
256
512
1024

Actually, just quoting the bash arithmetic part of the command works too:

$ parallel echo '$((2**{}))' ::: {5..10}
32
64
128
256
512
1024

The reason is that without quotes, bash will try to expand & evaluate the arithmetic before passing it to parallel, and 2**{} doesn’t mean anything to bash. The error message is actually from bash, not parallel:

$ echo $((2**{}))
-bash: 2**{}: syntax error: operand expected (error token is "{}")
Answered By: cas

@cas shows how to use the shell. Personally I like to do it using a {= perl =} replacement string:

parallel echo '{= $_=2**$_ =}' ::: {5..10}

but the difference is tiny and more just a matter of taste.

There are situations, where the Perl version is better: If you for some reason is forced to use a shell which does not have the $(( expression )) construct (e.g. fish) or need more computational functionality: parallel echo '{= $_=2**($_/2) =}'

Answered By: Ole Tange
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.