Подтвердить что ты не робот

Как изменить переменную пути в ZSH

В моем .bash_profile у меня есть следующие строки:

PATHDIRS="
/usr/local/mysql/bin
/usr/local/share/python
/opt/local/bin
/opt/local/sbin
$HOME/bin"
for dir in $PATHDIRS
do
    if [ -d $dir ]; then
        export PATH=$PATH:$dir
    fi
done

Однако я попытался скопировать это на мой .zshrc, а $PATH не установлен.

Сначала я помещал операторы echo внутри функции "if directory exists", и я обнаружил, что оператор if оценивал значение false, даже для явно существующих каталогов.

Затем я удалил проверку существующего каталога, а параметр $PATH был неправильно установлен следующим образом:

/usr/bin:/bin:/usr/sbin:/sbin:
/usr/local/bin
/opt/local/bin
/opt/local/sbin
/Volumes/Xshare/kburke/bin
/usr/local/Cellar/ruby/1.9.2-p290/bin
/Users/kevin/.gem/ruby/1.8/bin
/Users/kevin/bin

Ни одна из программ в нижних каталогах не найдена или не выполнена.
Что я делаю неправильно?

4b9b3361

Ответ 1

В отличие от других оболочек, zsh не выполняет разбиение слов или глобус после замены переменных. Таким образом, $PATHDIRS расширяется до одной строки, содержащей точно значение переменной, а не к списку строк, содержащих каждую отдельную часть с разделителем пробела.

Использование массива - лучший способ выразить это (не только в zsh, но и в ksh и bash).

pathdirs=(
    /usr/local/mysql/bin
    …
    ~/bin
)
for dir in $pathdirs; do
    if [ -d $dir ]; then
        path+=$dir
    fi
done

Поскольку вы, вероятно, не собираетесь ссылаться на pathdirs позже, вы также можете написать его inline:

for dir in \
  /usr/local/mysql/bin \
  … \
  ~/bin
; do
  if [[ -d $dir ]]; then path+=$dir; fi
done

Даже более короткий способ выразить это: добавьте все каталоги, которые вам нравятся в массив path, затем выберите те, которые существуют.

path+=/usr/local/mysql/bin
…
path=($^path(N))

N glob qualifier выбирает только существующие совпадения. Добавьте -/ в список классификаторов (т.е. (-/N) или (N-/)), если вы обеспокоены тем, что один из элементов может быть чем-то иным, чем каталог или символическая ссылка на один (например, сломанная символическая ссылка). Флаг расширения ^ гарантирует, что квалификатор glob применяется к каждому элементу массива отдельно.

Вы также можете использовать квалификатор N, чтобы добавить элемент, только если он существует. Обратите внимание, что вам нужно, чтобы globbing произошел, поэтому path+=/usr/local/mysql/bin(N) не работает.

path+=(/usr/local/bin/mysql/bin(N-/))

Ответ 2

Вы можете поместить

 setopt shwordsplit

в .zshrc. Тогда zsh выполнит разбиение мира, как и все оболочки Bourne. То, что по умолчанию выглядит noshwordsplit, является недостоверностью, которая вызывает много царапин на голове. Я был бы удивлен, если бы это был не FAQ. Давайте посмотрим... yup: http://zsh.sourceforge.net/FAQ/zshfaq03.html#l18 3.1: Почему $var, где var = "foo bar" не выполняет то, что я ожидаю?

Ответ 3

Все еще не уверен, в чем проблема (возможно, новые строки в $PATHDIRS)? но изменение синтаксиса массива zsh фиксировало его:

PATHDIRS=(
/usr/local/mysql/bin
/usr/local/share/python
/usr/local/scala/scala-2.8.0.final/bin
/opt/local/Library/Frameworks/Python.framework/Versions/2.6/bin
/opt/local/Library/Frameworks/Python.framework/Versions/2.7/bin
/opt/local/etc
/opt/local/bin
/opt/local/sbin
$HOME/.gem/ruby/1.8/bin
$HOME/bin)

и

path=($path $dir)