Shell Script: создание переменной с параметрами внутри

11

У меня есть команда rsync со следующими параметрами:

rsync -avz --{partial,stats,delete,exclude=".*"}

Я хочу поместить эти параметры в переменную, чтобы использовать ее после в скрипте. Что-то вроде этого:

#!/bin/bash
VAR=rsync -avz --{partial,stats,delete,exclude=".*"}
$VAR /dir1 /dir2

Я пробовал с кавычками, одинарные кавычки, скобки, но безуспешно.

Kellyson
источник
Аналогичный вопрос по SO: stackoverflow.com/questions/13365553/…
Barmar
Пройдя по этому маршруту раньше: убедитесь, что в вашей последней результирующей командной строке нет пустых строк. Если это так, rsync может использовать их в качестве параметров, и поскольку они невидимы, их довольно сложно отладить. У меня был пустой первый параметр, и rsync интерпретировал его как включение текущего каталога в исходные тексты для копирования.
Джо

Ответы:

12

Помещение сложной команды в переменную никогда не рекомендуется. Смотрите BashFAQ / 050 - я пытаюсь поместить команду в переменную, но сложные случаи всегда терпят неудачу!

Ваше требование становится действительно простым, если вы просто решите использовать функцию вместо переменной и передать ей аргументы.

Что-то типа

rsync_custom() {
    [ "$#" -eq 0 ] && { printf 'no arguments supplied' >&2; exit 1 ; }
    rsync -avz --{partial,stats,delete,exclude=".*"} "$@"
}

и теперь передайте необходимые аргументы ему как

rsync_custom /dir1 /dir2

Определение функции довольно просто, мы сначала проверяем количество входных аргументов, используя переменную, $#которая не должна быть нулевой. Мы выдаем сообщение об ошибке, в котором говорится, что аргументы не указаны. Если есть допустимые аргументы, то "$@"представляет фактические аргументы, предоставленные функции.

Если вы используете эту функцию довольно часто, например, в скриптах / командной строке, добавьте ее .bashrc, .bash_profileнапример, в файлы запуска оболочки .

Или, как уже отмечалось, возможно, стоит расширить расширение скобок, чтобы разделить аргументы для лучшей читаемости, так как

rsync_custom() {
    [ "$#" -eq 0 ] && { printf 'no arguments supplied' >&2; exit 1 ; }
    rsync -avz --partial --stats --delete --exclude=".*" "$@"
}
Inian
источник
5
VAR=rsync -avz --{partial,stats,delete,exclude=".*"}

Он пытается выполнить команду -avzс аргументами --partialи --statsт. Д. И с VARустановленным на rsyncв среде.

VAR='rsync -avz --{partial,stats,delete,exclude=".*"}'

Форма в кавычках не работает, потому что фигурные скобки не раскрываются в кавычках, а не внутри заданий, и они также не раскрываются после раскрытия переменной.

Если вам нужно сохранить аргументы командной строки в переменной, используйте массив:

args=(rsync -avz --{partial,stats,delete,exclude=".*"})

Теперь "${args[@]}"будет расширяться rsync, -avz, --partialи т.д. , как отдельные слова.

Массивы также позволяют вам добавлять опции в список, условно, если это необходимо, так что вы можете, например:

args=(this that)
if something ; then
    args+=(another_arg)
fi
"$cmd" "${args[@]}"
ilkkachu
источник
1

Вы можете по крайней мере частично сохранить параметры в переменной:

opts=$(echo --{ignore-case,word-regexp,count,exclude='"sys*.*"'})

Тестирование важно, потому что маскировка может быть трудной:

echo $opts
--ignore-case --word-regexp --count --exclude="sys*"

grep $opts bytes *.log 

Поскольку существует несколько альтернатив, таких как использование истории, использование псевдонима, использование функции, я не могу придумать очевидного варианта использования. Распределение параметров между различными программами редко бывает сложным, поэтому для специального решения для интерактивной оболочки псевдонимы выглядят лучшим способом:

alias cgrep='grep --ignore-case --word-regexp --count --exclude="sys*"'
cgrep bytes *.log

Ваш образец

VAR=rsync -avz --{partial,stats,delete,exclude=".*"}

не может работать, потому что назначение является endet в первом пробеле. Вы должны замаскировать пробелы:

VAR='rsync -avz --{partial,stats,delete,exclude=".*"}'

довольно опасная вещь для тестирования, с этой опцией --delete, не так ли? Поскольку параметры могут содержать снова "," и одинарные кавычки, маскирование может стать очень трудным в ближайшее время. Я бы пошел за псевдоним или полагаться на историю.

Псевдоним может быть сохранен в файле ~ / .bashrc для непрерывного использования в течение нескольких сеансов. Функции также могут быть сохранены в bashrc, но они вам нужны, только если вы хотите обработать параметры, переданные в функцию, которая будет оценена в них.

неизвестный пользователь
источник