Создавать списки аргументов, содержащие пробелы

В bash можно избежать аргументов, содержащих пробелы.

foo "a string"

Это также работает для аргументов команды или функции:

bar() {
    foo "[email protected]"
}

bar "a string"

До сих пор так хорошо, но что, если я хочу манипулировать аргументами до вызова foo?

Это не работает:

bar() {
    for arg in "[email protected]"
    do
        args="$args \"prefix $arg\""
    done

    # Everything looks good ...
    echo $args

    # ... but it isn't.
    foo $args

    # foo "$args" would just be silly
}

bar a b c

Итак, как вы создаете списки аргументов, когда аргументы содержат пробелы?

Ответ 1

Есть (по крайней мере) два способа сделать это:

(1.) Используйте массив и разворачивайте его с помощью "${array[@]}":

bar() {
    local i=0 args=()
    for arg in "[email protected]"
    do
        args[$i]="prefix $arg"
        ((++i))
    done

    foo "${args[@]}"
}

Итак, что мы узнали? "${array[@]}" до ${array[*]}, что "[email protected]" до $*.

(2). Если вы не хотите использовать массивы, вам нужно использовать eval:

bar() {
    local args=()
    for arg in "[email protected]"
    do
        args="$args \"prefix $arg\""
    done

    eval foo $args
}

Ответ 2

Вот более короткая версия: (пример построения аргументов для команды find)

dir=$(shift)
for f in "[email protected]" ; do
    args+=(-iname "*$f*")
done
find "$dir" "${args[@]}"

Ответ 4

Вы можете использовать массивы так же, как вы предлагаете, с небольшой детализацией. Строка, вызывающая foo, должна читать

 foo "${args[@]}"

Ответ 5

У меня тоже была проблема с этим. Я писал bash script для резервного копирования важных файлов на моем компьютере Windows (cygwin). Я тоже пробовал использовать массив, и у меня все еще были проблемы. Не уверен точно, как я его исправил, но вот части моего кода, которые важны в случае, если это поможет вам.

WORK="d:\Work Documents\*"
#   prompt and 7zip each file
for x in $SVN $WEB1 $WEB2 "$WORK" $GRAPHICS $W_SQL
do
    echo "Add $x to archive? (y/n)"
    read DO
    if [ "$DO" == "y" ]; then
        echo "compressing $x"
        7zip a $W_OUTPUT "$x"
    fi
    echo ""
done