Shell – What does ${PATH:+:${PATH}} mean

pathshellvariable substitution

I recently noticed the following in my cygwin profile, more precisely:

/usr/local/bin:/usr/bin${PATH:+:${PATH}}

What does it mean? Why is not just $PATH? Is this an 'if $PATH exists then add :$PATH'? My purpose is to swap the order and put the cygwin paths behind the windows path. In the past I would have

$PATH:/usr/local/bin:/usr/bin

but this confuses me. Maybe I should be doing

PATH="${PATH:+${PATH}:}/usr/local/bin:/usr/bin"

to append the : at the end of the $PATH?

Best Answer

The :+ is a form of parameter expansion:

${parameter:+[word]} : Use Alternative Value.

If parameter is unset or null, null shall be substituted; otherwise, the expansion of word (or an empty string if word is omitted) shall be substituted.

In other words, if the variable $var is defined, echo ${var:+foo} will print foo and, if it is not, it will print the empty string.

The second : is nothing special. It is the character used as a separator in the list of directories in $PATH. So, PATH="/usr/local/bin:/usr/bin${PATH:+:${PATH}}" is a shorthand way of writing:

if [ -z "$PATH" ]; then
    PATH=/usr/local/bin:/usr/bin
else
    PATH=/usr/local/bin:/usr/bin:$PATH
fi

It's just a clever trick to avoid adding an extra : when $PATH is not set. For example:

$ PATH="/usr/bin"
$ PATH="/new/dir:$PATH" ## Add a directory
$ echo "$PATH"
/new/dir:/usr/bin

But if PATH is unset:

$ unset PATH
$ PATH="/new/dir:$PATH"
$ echo "$PATH"
/new/dir:

A : by itself adds the current directory to the $PATH. Using PATH="/new/dir${PATH:+:$PATH}" avoids this. So sure, you can use PATH="${PATH:+${PATH}:}/usr/local/bin:/usr/bin" if you want to, or you can use PATH="$PATH:/usr/local/bin:/usr/bin" if you prefer. The only difference is that the former might add an extra :, thereby adding your current directory to your $PATH.

Related Question