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는 다차원 배열을 지원하지 않습니다. 이것을 더 깔끔하게 만들기 위해 좋은 패턴을 찾는 방법에 대한 아이디어가 있거나 두 번째 예와 비슷한 작업을 수행하는 사람이 있습니까? 감사해요!

답변1

이 방법은 각 매개변수에 하나씩 세 개의 배열을 사용합니다 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"

관련 정보