Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

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

3 Answers 3

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]}
done

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) ]
then
        echo "Different numbers of strings." >&2
else
        paste instances.1_per_line snapshots.1_per_line | while read inst snap
        do
                ec2-attach-volume -C cert.pem -K pk.pem --instance "$inst" \
                                --device /dev/sdf "$snap"
        done
fi
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: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1

share|improve this answer

Your Answer

 
discard

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.