0

When I run the following script in bash:

#!/bin/bash

names=("ALL" "no_C" "no_R" "no_Q")

for name in $names; do
    export name=$name
    mkdir -p $name
    ( echo 'selection' 'System' | gmx cluster -f ${name}_protein_only.trr -s ${name}_protein_only.pdb -n ${name}_index.ndx -g ${name}/cluster.log -cutoff 0.2 -fit -method gromos -o ${name}/cluster.output -dist ${name}/rmsd-dist.xvg -av -cl ${name}/clusters.pdb ) &
done
wait

The for loop won't loop until the subshell has completed, even though I've put it into the background with '&'. If I run this same script in zsh, it runs as expected (4 parallel tasks). Is this a bug or am I missing something?

2 Answers2

1

You need to use a different notation for all the elements of an array in Bash (see Arrays and Shell parameter expansion):

for name in "${name[@]}"; do

When you specify $name and name is an array, Bash treats it as ${name[0]}.

I used this variant on your code to demonstrate:

#!/bin/bash

names=("ALL" "no_C" "no_R" "no_Q")

for name in "${names[@]}"
do
    export name=$name
    mkdir -p $name
    ( echo $name 'selection' 'System' | sed s/s/z/g; sleep 3 ) &
done
wait
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
1

I believe what Jonathan Leffler wrote is correct in terms of the definition of a Bash array and how to loop through it.

But, if you wanted to define names as a series of strings like this:

names="ALL no_C no_R no_Q"

Then you could still loop through it using:

for name in $names; do
  .... do something with name
done
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
yftse
  • 183
  • 6
  • That is another way of dealing with the problem. It would not be a good idea if any of the names currently in the array themselves contained spaces. At that point, an array is _definitely_ the correct way to go. – Jonathan Leffler Jan 17 '16 at 03:17