Adding paths to PATH using a multi-line syntax

10,985

Solution 1

I do not know if it works in zsh, but it works in bash:

PATH=$(paste -d ":" -s << EOF 
$PATH
/my/path/1
/my/path/2
/my/path/3
EOF
)

Edit and even shorter:

PATH=`paste -d ":" -s << EOF 
$PATH
/my/path/1
/my/path/2
/my/path/3
EOF`

And without spawning a process:

new_path=(
"$PATH"
/my/path/1
/my/path/2
/my/path/3)
OLD_IFS="$IFS"
export IFS=":"
PATH="${new_path[*]}"
export IFS="$OLD_IFS"

The double quotes are important arround $PATH, $IFS, ${new_path[*]} and $OLD_IFS to keep spaces in the variables and avoid shell interpretation of IFS.

Update2 with comments and empty line management using sed:

PATH=`sed -e '/^#/'d -e '/^$/'d << EOF | paste -d ":" -s 
$PATH
/my/path/1
# This is a comment.
/my/path/2

/my/path/3
EOF`

The comment character must be the 1st char on the line, and empty lines should be completely empty. To manage spaces and tabs before comment and on empty lines, use sed -e '/^[ \t]*#/'d -e '/^[ \t]*$/'d instead (tabs to be tested as it might be specific to the sed implementation).

Solution 2

Not an interesting solution at all, but very portable:

PATH=${PATH}:/my/path/1
PATH=${PATH}:/my/path/2
PATH=${PATH}:/my/path/3

Solution 3

In zsh, $path is an array:

path=(
    $path
    ~/.local/bin
    ~/.gem/ruby/2.0.0/bin
)

Note: both path is lowercase.

Solution 4

In zsh, if you're adding directories at the end of the path:

path+=/my/path/1
path+=/my/path/2
path+=(/path/to/app/{i386,share}/bin)

Portably: How to correctly add a path to PATH?

You can use glob qualifiers to exclude entries that are not existing directories or symbolic links to such. This may or may not be desirable, depending on whether you expect the directories to possibly be added later during the session (e.g. if they're on remote filesystems). You can't do that with the path+=/my/path syntax because the right-hand side is in a string context and so doesn't undergo globbing; you can do it with path+=(/my/path) since each array element is expanded in a list context.

path+=(/path/to/app/{i386,share}/bin(-/N))
Share:
10,985

Related videos on Youtube

Amelio Vazquez-Reina
Author by

Amelio Vazquez-Reina

I'm passionate about people, technology and research. Some of my favorite quotes: "Far better an approximate answer to the right question than an exact answer to the wrong question" -- J. Tukey, 1962. "Your title makes you a manager, your people make you a leader" -- Donna Dubinsky, quoted in "Trillion Dollar Coach", 2019.

Updated on September 18, 2022

Comments

  • Amelio Vazquez-Reina
    Amelio Vazquez-Reina over 1 year

    As far as I understand, the usual way to add a path to the PATH environment variable is by concatenating paths separated by the : character.

    For example, if I want to add three paths to it /my/path/1, /my/path/2 and /my/path/3, I would have to do it as follows:

    PATH=$PATH:/my/path/1:/my/path/2:/my/path/3
    

    which is not easy to read.

    Is there a way to define or add paths to the PATH variable using a multi-line syntax? Perhaps using arrays? I am looking for something like this:

    PATH = 
    $PATH
    /my/path/1
    /my/path/2
    /my/path/3
    

    In case there are interesting solutions that are shell specific, I am looking for a solution in zsh.

  • bsd
    bsd over 12 years
    This is typical of what I've seen over the years. One can easily reorder the paths or even change an element to be PATH=/my/path/1:${PATH} to force prepending.
  • Amelio Vazquez-Reina
    Amelio Vazquez-Reina over 12 years
    I tested the last snippet in zsh and it works. I also like that it's a bit cleaner (one path per line) than the other solutions. Can the solution accomodate commented lines (paths)? How about empty lines?
  • jfg956
    jfg956 over 12 years
    And with sed, if you want to play, you can avoid the paste process with a more complicated script.
  • clerksx
    clerksx over 12 years
    You could also use += to avoid having to completely rebuild the string.
  • Simon Gates
    Simon Gates over 12 years
    And you don't even need to use the braces. Colons can't be used in environment variable names so there's no ambiguity to resolve.
  • ruakh
    ruakh over 12 years
    +1 for not being interesting. Interesting can be good sometimes, but this isn't one of those times! (Especially since the OP explicitly mentioned "not easy to read" as a problem.)
  • vonbrand
    vonbrand about 11 years
    That depends on the shell, not all handle this.
  • Kabie
    Kabie about 11 years
    @vonbrand: Yes, But works in zsh. I think it worth to mention.
  • user281806
    user281806 almost 11 years
    +1 (This question is tagged zsh)
  • void.pointer
    void.pointer almost 10 years
    Is it OK to use indentation for the paths in the paste solution?
  • mbigras
    mbigras over 7 years
    for anyone interested in learning more about the $path vs. $PATH distinction check out this post
  • John P
    John P over 7 years
    @ChrisDown Is there a syntax which prepends without rebuilding the string?