2

I use GNU-parallel to call a function foo repeatedly. The function takes two arguments, a filename (a in the example below, saved in the array A) and an array of filters (B below, with b as elements of B).

The function should iterate over all combinations of A and B, however, the catch is, that I actually use parallel only to iterate over A, while providing B to each function call.

As a minimum example:

#!/bin/bash

A=("1" "2" )
B=("X" "Y")

foo() {
    a=$1 # a single element of A
    B=$2 # the whole array B
    for b in "${B[@]}"; do
        printf "a = %s; b = %s\n" $a $b
    done
    echo "-----------------"
}
export -f foo

# goal:
echo "Sequential (aka, the target) ==="
for a in "${A[@]}"; do
    foo $a $B
done

Results

Sequential (aka, the target) ===
a = 1; b = X
a = 1; b = Y
-----------------
a = 2; b = X
a = 2; b = Y
-----------------

Mind that instead of having a single call to each combination, we have only for each A a call and then within the function iterate over B.

Parallel tries:

Try 1

parallel foo ::: "${A[@]}" ::: "${B}"

Results in

a = 1; b = X
-----------------
a = 2; b = X
-----------------

(missing the second argument of B)

Try 2

parallel foo ::: "${A[@]}" ::: "${B[@]}" 

Results in

a = 1; b = X
-----------------
a = 1; b = Y
-----------------
a = 2; b = X
-----------------
a = 2; b = Y
-----------------

(one call per combination, not one call per A, then iterating over B)

I have looked through the manual and SO but couldn't find a solution.

Edit

I have the feeling that it should work when I export the array B directly, but get no results as well

foo2() {
    a=$1 # a single element of A
    # B=$2 # the whole array B
    for b in "${B[@]}"; do
        printf "a = %s; b = %s\n" $a $b
    done
    echo "-----------------"
}
export -f foo2
export B

parallel foo ::: "${A[@]}"

Results in

-----------------
-----------------

(apparently empty B)

1 Answer 1

2

Your problem stems from B being an array. I have never seen an array being passed as an argument to a function before, and I am not sure it can be done.

The second issue is that while you can export both functions and variables, you cannot export an array without cheating: Exporting an array in bash script

GNU Parallel makes it easy to cheat by using env_parallel. This will export the full environment to the shell running the command: Arrays, variables, aliases, and functions. It will even do so when running commands remotely.

env_parallel has improved a lot the past year, so upgrade if the version you have causes problems.

#!/bin/bash                                                                        

A=("1" "2" )
B=("X" "Y")

foo() {
    a=$1 # a single element of A                                                   
#    B=$2 # the whole array B                                                      
    for b in "${B[@]}"; do
        printf "a = %s; b = %s\n" $a $b
    done
    echo "-----------------"
}

# If you have earlier run 'env_parallel --install'                                 
# to activate env_parallel in your shell                                           
# this should work.                                                                
env_parallel foo ::: "${A[@]}"

# If you have not, then this should work:
. `which env_parallel.bash`
env_parallel foo ::: "${A[@]}"
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.