Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

instances contains several whitespace separated strings, as does snapshots. I want to run the command below, with each instance-snapshot pair.

ec2-attach-volume --instance $instances --device /dev/sdf $snapshots

For example, if instances contains A B C, and snapshots contains 1 2 3, I want the command to be called like so:

ec2-attach-volume -C cert.pem -K pk.pem --instance A --device /dev/sdf 1
ec2-attach-volume -C cert.pem -K pk.pem --instance B --device /dev/sdf 2
ec2-attach-volume -C cert.pem -K pk.pem --instance C --device /dev/sdf 3

I can do either one or the other with xargs -n 1, but how do I do both?

share|improve this question
up vote 0 down vote accepted

Using the bash shell, one possible method is:

instances=( `cat instances` )
snapshots=( `cat snapshots` )

for i in ${!instances[@]}; do
    ec2-attach-volume -C cert.pem -K pk.pem \
        --instance ${instances[i]} --snapshot ${snapshots[i]}

Here ${!instances[@]} expands to all indexes of the instances array (0, 1, 2, and so on). You can examine the array contents by doing declare -p instances snapshots after the first two lines.

share|improve this answer

Here’s an approach that includes (some) error handling:

xargs –n 1 < instances > instances.1_per_line    # “xargs –n 1” is equivalent to
xargs –n 1 < snapshots > snapshots.1_per_line    # “xargs –n 1 echo”.
if [ $(wc –l < instances.1_per_line)  !=  $(wc –l < snapshots.1_per_line) ]
        echo "Different numbers of strings." >&2
        paste instances.1_per_line snapshots.1_per_line | while read inst snap
                ec2-attach-volume -C cert.pem -K pk.pem --instance "$inst" \
                                --device /dev/sdf "$snap"
rm instances.1_per_line snapshots.1_per_line

This may work better than grawity’s answer for large files, as it doesn’t need to read the files into memory.  And this may work better in older versions of bash.  (If $(command) doesn’t work, try `command`.)  On the other hand, my answer will fail if any of the strings in the files contain quote characters.

share|improve this answer

To do it in parallel you can use GNU Parallel:

parallel --xapply ec2-attach-volume --instance {1} --device /dev/sdf {2} ::: `cat instances` ::: `cat snapshots`

Watch the intro videos to learn more:

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.