Итерация по наборам аргументов команды в 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 не поддерживает многомерные массивы. Есть ли у кого-нибудь идеи для хорошего шаблона, чтобы сделать это чище или сделать что-то подобное по дизайну моему второму примеру? Благодаря!

Этот подход использует три массива, по одному для каждого аргумента 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") 

Я действительно не вижу необходимости в массивах, и я бы пошел на что-то простое:

 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"