2012-02-19 2 views
21

В моих .bash-profile У меня есть следующие строки:Как изменить переменную пути в ZSH

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 

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

ответ

48

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

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

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

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

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)) 

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

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

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

+1 - Два дополнительных подсказки, полезных для '$ PATH' манипуляции в' zsh' (для любого проходящего мимо): * (1) * для добавления вместо добавления: 'path [1,0] =/path/to/dir' и * (2) *, если вы используете globbing для поиска dirs, вам не нужно использовать цикл for, а вместо этого просто нужно «path + = ($ PWD/node_modules/**/bin ') (также работает с * (1) *). – unthought

+0

Спасибо, я использовал ваше предложение, с path = ($^path (N- /)). Теперь есть способ гарантировать, что те же самые диски не дублируются в $ PATH каждый раз, когда я запускаю source ~/.zshrc? Спасибо – stansult

+2

@stansult [Есть ли способ добавить каталог в мой PATH в zsh, только если он еще не присутствует?] (Http://unix.stackexchange.com/questions/62579/is-there-a-way- to-add-a-directory-to-my-path-in-zsh-only-if-its-not-already-pre) – Gilles

2

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

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) 
5

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

setopt shwordsplit 

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