Bashでコマンドパラメータセットを繰り返す

Bashでコマンドパラメータセットを繰り返す

順番に(技術的には並列に)実行する必要があるコマンドのパラメータには、いくつかの「グループ」があります。また、各コマンドを実行した後も同じロジックを繰り返す必要があります。

#!/bin/bash

local pids=()

# Run commands in parallel.
my_command "$URL_ONE"   "$URL_ONE_TEXT"    "${TMP_DIR}/some_dir" &
pids+=("$!")

my_command "$URL_ONE"   "$URL_TWO_TEXT"    "${TMP_DIR}/some_similar_dir" &
pids+=("$!")

my_command "$URL_TWO"   "$URL_TWO_TEXT"    "${TMP_DIR}/third_dir" &
pids+=("$!")

my_command "$URL_THREE" "$URL_THREE_TEXT"  "${TMP_DIR}/fourth_dir" &
pids+=("$!")

# ...

# Wait for parallel commands to complete and exit if any fail.
for pid in "${pids[@]}"; do
    wait "$pid"
    if [[ $? -ne 0 ]]; then
        errecho "Failed."
        exit 1
    fi
done

他の部分を頻繁に繰り返すのではなく、パラメータのpids+=("$!")配列/セットを定義し、それを繰り返し、各パラメータセットに対して同じロジックを実行します。たとえば、

#!/bin/bash

# This wouldn't actually work...
ARG_SETS=(
    ("$URL_ONE"   "$URL_ONE_TEXT"   "${TMP_DIR}/some_dir")
    ("$URL_ONE"   "$URL_TWO_TEXT"   "${TMP_DIR}/some_similar_dir")
    ("$URL_TWO"   "$URL_TWO_TEXT"   "${TMP_DIR}/third_dir")
    ("$URL_THREE" "$URL_THREE_TEXT" "${TMP_DIR}/fourth_dir")
)
for arg1 arg2 arg3 in "$ARG_SETS[@]"; do
    my_command "$arg1" "$arg2" "$arg3" &
    pids+=("$!")
done

しかし、Bashは多次元配列をサポートしていません。これをよりきれいにするために良いパターンを見つける方法についてのアイデアがありますか、または2番目の例と同様のタスクを実行する人がいますか?ありがとうございます!

答え1

この方法では、各パラメータに1つずつ3つの配列を使用しますmy_command

pids=()

a=("$URL_ONE"               "$URL_ONE"                      "$URL_TWO"                  "$URL_THREE")
b=("$URL_ONE_TEXT"          "$URL_TWO_TEXT"                 "$URL_TWO_TEXT"         "$URL_THREE_TEXT")
c=("${TMP_DIR}/some_dir"    "${TMP_DIR}/some_similar_dir"   "${TMP_DIR}/third_dir"  "${TMP_DIR}/fourth_dir")

for i in ${!a[@]}
do
    my_command "${a[$i]}" "${b[$i]}" "${c[$i]}" &
    pids+=("$!")
done

# Wait for parallel commands to complete and exit if any fail.
for pid in "${pids[@]}"
do
    if ! wait "$pid"
    then
        errecho "Failed."
        exit 1
    fi
done

代替スタイル

実行するコマンドの数に応じて、配列定義の次の代替方法を検討できます。

a=();              b=();                   c=()
a+=("$URL_ONE");   b+=("$URL_ONE_TEXT");   c+=("${TMP_DIR}/some_dir")
a+=("$URL_ONE");   b+=("$URL_TWO_TEXT");   c+=("${TMP_DIR}/some_similar_dir")
a+=("$URL_TWO");   b+=("$URL_TWO_TEXT");   c+=("${TMP_DIR}/third_dir")
a+=("$URL_THREE"); b+=("$URL_THREE_TEXT"); c+=("${TMP_DIR}/fourth_dir")

答え2

私は本当に配列が必要だとは思わず、次のような単純なものを使用します。

f(){
  my_command "$@" &
  pids+=("$!")
}

f "$URL_ONE"   "$URL_ONE_TEXT"   "${TMP_DIR}/some_dir"
f "$URL_ONE"   "$URL_TWO_TEXT"   "${TMP_DIR}/some_similar_dir"
f "$URL_TWO"   "$URL_TWO_TEXT"   "${TMP_DIR}/third_dir"
f "$URL_THREE" "$URL_THREE_TEXT" "${TMP_DIR}/fourth_dir"

関連情報