44

I want to show my PATH environment variable in a more human-readable way.

$ echo $PATH
/Users/arturo/.rvm/gems/ruby-1.9.3-p392/bin:/Users/arturo/.rvm/gems/ruby-1.9.3-p392@global/bin:/Users/arturo/.rvm/rubies/ruby-1.9.3-p392/bin:/Users/arturo/.rvm/bin:/usr/local/git/bin:/Users/arturo/.gvm/groovy/current/bin:/Users/arturo/.gvm/grails/current/bin:/Users/arturo/.gvm/griffon/current/bin:/Users/arturo/.gvm/gradle/current/bin:/Users/arturo/.gvm/lazybones/current/bin:/Users/arturo/.gvm/vertx/current/bin:/Users/arturo/.gvm/bin:/Users/arturo/.gvm/ext:/usr/local/git/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/local/git/bin

I'm thinking in something like this:

$ echo $PATH | some cut and awk magic
/Users/arturo/.rvm/gems/ruby-1.9.3-p392/bin
/Users/arturo/.rvm/gems/ruby-1.9.3-p392@global/bin
/Users/arturo/.rvm/rubies/ruby-1.9.3-p392/bin
/Users/arturo/.rvm/bin
...
62

You can use tr.

$ tr ':' '\n' <<< "$PATH"
/Users/arturo/.rvm/gems/ruby-1.9.3-p392/bin
/Users/arturo/.rvm/gems/ruby-1.9.3-p392@global/bin
/Users/arturo/.rvm/rubies/ruby-1.9.3-p392/bin
...

You can also do this in some shells (tested in bash and zsh):

echo -e ${PATH//:/\\n}

In zsh, you can use the $path variable to see your path with spaces instead of colons.

$ echo $path
/Users/arturo/.rvm/gems/ruby-1.9.3-p392/bin /Users/arturo/.rvm/gems/ruby-1.9.3-p392@global/bin /Users/arturo/.rvm/rubies/ruby-1.9.3-p392/bin /Users/arturo/.rvm/bin

Which can be combined with printf or print.

$ printf "%s\n" $path
/Users/arturo/.rvm/gems/ruby-1.9.3-p392/bin
/Users/arturo/.rvm/gems/ruby-1.9.3-p392@global/bin
/Users/arturo/.rvm/rubies/ruby-1.9.3-p392/bin
...
$ print -l $path
/Users/arturo/.rvm/gems/ruby-1.9.3-p392/bin
/Users/arturo/.rvm/gems/ruby-1.9.3-p392@global/bin
/Users/arturo/.rvm/rubies/ruby-1.9.3-p392/bin
...

The <<< operators are called herestrings. Herestrings pass the word to their right to the standard input of the command on their left.

$ cat <<< 'Hello there'
Hello there

If your shell doesn't support them, use echo and a pipe.

$ echo 'Hello there' | cat
Hello there
  • 2
    Interesting the use of the here-string, I'd do the following: echo $PATH | tr ':' '\n' but is more clear your solution. – Arturo Herrero Jun 20 '13 at 15:37
  • 1
    I added a bit to my answer to explain the use of herestrings to any passersby. – user26112 Jun 20 '13 at 15:45
  • In zsh, print -l $path saves a few keystrokes. It fails if $path contains backslashes, but that's highly unusual. – Gilles 'SO- stop being evil' Jun 20 '13 at 18:10
  • Note that some of those will fail to display the empty entries in $PATH. – Stéphane Chazelas Jun 20 '13 at 19:37
  • @StephaneChazelas: I never thought about that. The first two display empty entries. The zsh-only ones do not. – user26112 Jun 20 '13 at 19:48
4

Here's a quick way with bash

OLDIFS=$IFS IFS=: arr=($PATH) IFS=$OLDIFS
printf "%s\n" "${arr[@]}"
  • 4
    You can avoid saving/restoring IFS by using a subshell. e.g. (IFS=: arr=($PATH); printf "%s\n" "${arr[@]})") – Nick Jun 20 '13 at 18:39
  • 1
    That will also fail to display an empty entry in most shells if it's last (/bin:/usr/bin: used to be a common value for $PATH) – Stéphane Chazelas Jun 20 '13 at 19:38
  • In can also fail if $PATH contains some wildcard characters (unlikely) – Stéphane Chazelas Jun 20 '13 at 19:53
  • As you specified bash anyway, you may use IFS=: read -a arr <<< "$PATH" for the splitting part. That way IFS's new value will be used only while executing the read, so no need to restore it. pastebin.com/7E7C4AcR – manatwork Jun 21 '13 at 6:36
  • Thanks all for the feedback. @manatwork, do you know why IFS's new value persists after array creation but not after executing read? – iruvar Jun 21 '13 at 13:14
2

Expanding on Smith John's solution, this makes for a nice alias in your .bash_profile:

alias MyPath='echo -e ${PATH//:/\\n}'
1

Note that an unset PATH has a different meaning from an empty PATH. An empty PATH contains one empty element, and that means looking for executables in the current directory only, an unset PATH means to search for executables in a default list of directories (but note that on some systems, not every tool agrees on the content of that list)

In zsh:

if (($+PATH)); then
  echo "$#path element(s):"
  printf '%q\n' "$path[@]"
else
  echo "PATH unset"
fi

In POSIX shells (note that zsh even in sh mode is not POSIX in that regard):

if [ -n "${PATH+.}" ]; then
  (
    p=$PATH:
    set -f
    IFS=:
    set -- $p
    echo "$# element(s):"
    printf '"%s"\n' "$@"
  )
else
  echo "PATH unset"
fi

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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