2012-02-19 14 views
21

W moich bash_profile Mam następujące linie:Jak edytować zmienną path w 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 

Jednak starałem kopiując to do mojego .zshrc i $PATH nie jest ustawiony.

Najpierw wstawiam instrukcje echo do funkcji "jeśli katalog istnieje" i odkryłem, że instrukcja if oceniała wartość false, nawet dla wyraźnie istniejących katalogów.

Potem usuwa katalog-exists sprawdzić, a $PATH był nieprawidłowo ustawione tak:

/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 

Żaden z programów w dolnych katalogów były znalezione lub wykonywane.
Co robię źle?

Odpowiedz

48

przeciwieństwie do innych powłok zsh nie wykonuje dzielenie słowo lub masek po zmiennym zmiany. Tak więc $PATHDIRS rozwija się do pojedynczego łańcucha zawierającego dokładnie wartość zmiennej, a nie do listy ciągów znaków zawierających każdy oddzielony fragmentami wartości rozdzielonych białymi znakami.

Użycie tablicy jest najlepszym sposobem wyrażenia tego (nie tylko w zsh, ale także w ksh i bash).

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

Ponieważ prawdopodobnie nie będzie odnosić się do pathdirs później, równie dobrze można napisać inline:

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

Jest nawet krótszy sposób wyrazić to: dodaj wszystkie katalogi, które lubisz do macierzy path, a następnie wybierz te, które istnieją.

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

The Nglob qualifier wybiera tylko te mecze, które istnieją. Dodaj do listy -/ kwalifikatorem (tj (-/N) lub (N-/)) Jeśli martwisz się, że jednym z elementów może być coś innego niż katalogu lub dowiązania symbolicznego do jednego (np złamaną dowiązania symbolicznego). Dzięki temu kwalifikator globu ma zastosowanie do każdego elementu tablicy osobno.

Możesz również użyć kwalifikatora N, aby dodać element tylko wtedy, gdy istnieje. Zauważ, że potrzebujesz globowania, więc path+=/usr/local/mysql/bin(N) nie będzie działać.

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

+1 - Dwie dodatkowe szybkie wskazówki przydatne do manipulacji '$ PATH' w' zsh' (dla każdego, kto przechodzi): * (1) *, aby wstawić zamiast dodawać: 'ścieżka [1,0] =/ścieżka/to/dir' i * (2) * jeśli używasz globowania do znalezienia katalogów, nie musisz używać pętli for, a zamiast tego po prostu wykonaj 'path + = ($ PWD/node_modules/**/bin ') (działa również z * (1) *). – unthought

+0

Dzięki, użyłem twojej sugestii, z path = ($^path (N- /)). Czy istnieje sposób na zapewnienie, że te same katalogi nie będą duplikowane w zmiennej $ PATH za każdym razem, gdy uruchomię źródło ~/.zshrc? Dzięki – stansult

+2

@stansult [Czy istnieje sposób na dodanie katalogu do mojej PATH w zsh tylko wtedy, gdy nie jest już obecny?] (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

Nadal nie wiem, co problemem było (może newlines w $ PATHDIRS)? ale zmienia się zsh składni tablicy poprawiony:

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) 

i

path=($path $dir) 
5

Można umieścić

setopt shwordsplit 

w .zshrc. Następnie zsh wykona podział świata, tak jak robią to wszystkie powłoki Bourne'a.To, że domyślnie wygląda na noshwordsplit, to błąd, który powoduje wiele problemów z drapaniem głowy. Byłbym zaskoczony, gdyby to nie było FAQ. Zobaczmy ... tak: http://zsh.sourceforge.net/FAQ/zshfaq03.html#l18 3.1: Dlaczego $ var gdzie var = "foo bar" nie spełnia moich oczekiwań?