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

Я не знаю ни о каких командах, но довольно легко записать сценарий:

#!/bin/bash    
ARG=$1
while [[ "$ARG" != "." && "$ARG" != "/" ]]
do
        ls -ld -- "$ARG"
        ARG=`dirname -- "$ARG"`      
done

Пример:

$ perms.sh /tmp/1/2/3/hello.txt

-rw-rw-r--    1 user    group          0 Jan 14 16:59 /tmp/1/2/3/hello.txt
drwxrwxr-x    2 user    group       4096 Jan 14 16:59 /tmp/1/2/3
drwxrwxr-x    3 user    group       4096 Jan 14 16:43 /tmp/1/2
drwxrwxr-x    3 user    group       4096 Jan 14 16:43 /tmp/1
drwxrwxrwt   12 root     root       4096 Jan 14 17:02 /tmp
6
27.08.2011, 03:32
3 ответа

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

rsync ${=OPTS} $SRC $DST 

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

Из страницы справочника:

Одно различие, с которым обычно встречаются [в zsh] это, переменные, которыми заменяют на командную строку, не разделяются на слова. См. описание опции оболочки SH_WORD_SPLIT в разделе 'Parameter Expansion' в zshexpn(1). В zsh, можно или явно запросить разделение (например. ${=foo}) или используйте массив, когда Вы захотите, чтобы переменная расширилась больше чем до одного слова. Посмотрите раздел 'Array Parameters' в zshparam(1).

11
27.01.2020, 20:20
  • 1
    Есть ли так или иначе, я могу сделать это портативным для избиения? Я хочу использовать тот же сценарий/функцию, чтобы быть применимым и в ударе и в zsh. –  balki 09.09.2011, 17:09
  • 2
    @balki: можно запустить сценарий с set -o shwordsplit 2>/dev/null сказать zsh использовать sh разделение слова. Или можно использовать массивы, как описано Gilles. –  Stéphane Gimenez 09.09.2011, 17:43

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

$OPTS список слов, не слова. Если Вам только нужен Ваш сценарий для работы в ksh, ударе и 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, и это не на других оболочках.

emulate ksh >/dev/null 2>/dev/null
7
27.01.2020, 20:20

Для завершения ответа Stéphane Gimenez (я еще не могу прокомментировать) одно решение состоит в том, чтобы сделать сценарий портативным для избиения путем проверки, используете ли Вы zsh и затем преобразуйте $OPTS в массив как это

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

Затем Ваша команда rsync будет работать.

3
27.01.2020, 20:20

Теги

Похожие вопросы