Расширение переменных в zsh

Сценарий ниже работает в bash, но не в zsh. Я думаю, это потому, что в переменной OPTS я «расширяюсь» (не уверен, что это правильное слово) переменная $EXCLUDE , и этот синтаксис не работает в zsh. Как заменить эту строку, чтобы она работала на zsh?

 SRC="/path_to_source" DST="/path_to_dest" EXCLUDE=".hg" OPTS="-avr --delete --progress --exclude=${EXCLUDE} --delete-excluded" rsync $OPTS $SRC $DST 

3 Solutions collect form web for “Расширение переменных в zsh”

Проблема здесь в том, что $OPTS не разделяется на несколько аргументов в командной строке rsync . В синтаксисе zsh используйте:

 rsync ${=OPTS} $SRC $DST 

(альтернативой является симуляция стандартного поведения оболочки во всем мире с опцией -o shwordsplit …)

С manpage:

Обычно встречающаяся разница [в zsh ] заключается в том, что переменные, замещенные в командной строке, не разбиваются на слова. См. Описание опции оболочки SH_WORD_SPLIT в разделе «Расширение параметров» в zshexpn(1) . В zsh вы можете либо явно запросить расщепление (например, ${=foo} ), либо использовать массив, если хотите, чтобы переменная расширялась до нескольких слов. См. Раздел «Параметры массива» в zshparam(1) .

Проблема не исходит от $EXCLUDE , она исходит от $OPTS . Ваш сценарий основан на разбиении слов на $OPTS . Это плохая идея; например, он будет терпеть неудачу, если вы когда-либо измените $EXCLUDE чтобы содержать шаблон, и --exclude=$EXCLUDE подходит для соответствия файлу в текущем каталоге или если вы когда-либо изменяете $EXCLUDE чтобы содержать пробелы.

$OPTS – это список слов, а не слово. Если вам нужен только ваш скрипт для работы в ksh, bash и zsh, сделайте его массивом:

 SRC="/path_to_source" DST="/path_to_dest" EXCLUDE=".hg" OPTS=(-avr --delete --progress --exclude="$EXCLUDE" --delete-excluded) rsync "${OPTS[@]}" "$SRC" "$DST" 

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

 rsync $OPTS $SRC $DST 

Если вы хотите, чтобы скрипт работал в каждой оболочке, вам нужно использовать позиционные параметры. Они являются единственным доступным массивом.

 set -- -avr --delete --progress --exclude="$EXCLUDE" --delete-excluded rsync "$@" "$SRC" "$DST" 

Если у вас есть сценарий оболочки, который вы хотите легко запускать с помощью zsh, поместите эту строку в начало – она ​​сообщает zsh действовать как ksh, и это не-op для других оболочек.

 emulate ksh >/dev/null 2>/dev/null 

Чтобы завершить ответ Стефана Гименеса (я еще не могу прокомментировать), одно из решений заключается в том, чтобы сделать ваш скрипт переносимым, если вы используете zsh а затем преобразуете $OPTS в массив, подобный этому

 [ -n "${ZSH_VERSION:-}" ] && set -A OPTS ${=OPTS} 

Тогда ваша команда rsync будет работать.

  • Получить zsh, чтобы сообщить каталог emacs
  • Показывать материал под подсказкой в ​​командной строке?
  • Почему эта команда для копирования файлов в цикле for работает в bash, но не в zsh?
  • таблица ключевых привязок?
  • Переменные среды установки OS X
  • Изменение динамического названия tmux-окна до последней строки вывода команды
  • Команда ведет себя по-разному при сохранении в файле * .sh
  • zsh: использовать setopt AUTO_MENU условно, в зависимости от $ PWD
  • Как вы управляете своими псевдонимами bash / zsh?
  • Файлы в $ ZSH_CUSTOM, не загруженные oh-my-zsh
  • dircolors on zsh: непризнанные ключевые слова: MULTIHARDLINK, RESET & CAPABILITY
  • bash выбрасывает «set-ena», когда я нажимаю / пишу b в терминале
  • Linux и Unix - лучшая ОС в мире.