Как изменить переменную пути в 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
Ни одна из программ в нижних каталогах не найдена или не выполнена.
Что я делаю неправильно?
Ответы
Ответ 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)