Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

For some reason, my $PATH variable is not being set properly which means I can't run a lot of commands I would like to. Here are the relevant lines from my .zshrc file:

if [[ -f ~/.profile]]; then
    source ~/.profile
fi

Here is my .profile file:

pathdirs=( 
    ~/.rvm/bin
    /usr/local/heroku/bin
    /usr/local/shar/scala-2.10.0/bin
)

for dir in $pathdirs; do
    if [[ -d $dir ]]; then
        path+=$dir
    fi
done

When I echo my $PATH variable, none of these three items shows up. All I get when I run cat $PATH is /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin:/usr/local/git/bin: /usr/texbin. Could anyone see if I'm doing something wrong?

share|improve this question
    
Hmm not sure what you mean. My .zshrc is run every time a new shell is open. Within my .zshrc, I have a statement that loads my .profile where I keep all of my $PATH related needs. What's the confusion? –  Cody Ma Apr 28 at 2:07
    
What does putting a echo $dir right before path+=... show you? –  slm Apr 28 at 2:46
    
Please don't cat $PATH... That sounds dangerous –  mikeserv Apr 28 at 3:39
    
In bash at least, you need to do path+=($dir) rather than path+=$dir. –  Mikel Apr 28 at 3:48
1  
.profile is traditionally read by all Bourne/POSIX-compliant shells. In which case you'd need "${pathdirs[@]}" rather than $pathdirs. –  Mikel Apr 28 at 3:51

1 Answer 1

Here's a function I wrote for another answer:

_path_assign() { oFS=$IFS ; IFS=: ; add=$* ; unset P A ; A=
    set -- ${PATH:=$1} ; for p in $add ; do {
        [ -z "${p%-[AP]}" ] && { unset P A
                eval ${p#-}= ; continue ; }
        for d ; do [ -z "${d%"$p"}" ] && break
        done ; } || set -- ${P+$p} $* ${A+$p}
        done ; export PATH="$*" ; IFS=$oFS
}

% PATH=/usr/bin:/usr/yes/bin
% _path_assign \
    /usr/bin \
    /usr/yes/bin \
    /usr/bin/nope \
    -P \
    /usr/nope/bin \
    /usr/bin \
    -A \
    /nope/usr/bin \
    /usr/nope/bin

% echo $PATH

OUTPUT:

/usr/nope/bin:/usr/bin:/usr/yes/bin:/usr/bin/nope:/nope/usr/bin

All arguments following a -P are prepended to $PATH if they are not already included, and same for -A but they're appended. If you want to verify they're actual directories first you can change:

|| set -- ${P+$p} $* ${A+$p}
done

to:

|| { [ -d "$p" ] && set -- ${P+$p} $* ${A+$p}
} ; done

You should probably make sure zsh handles $IFS more portably by just adding:

[ "${SHELL##*/}" = "zsh" ] && emulate sh

to the first line.

Make those two changes and all of the code you have in your question could be replaced with this function and:

test -f ~/.profile && . $_
_path_assign ~/.rvm/bin \
    /usr/local/heroku/bin \
    /usr/local/shar/scala-2.10.0/bin
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.