Что означает $ {PATH: +: $ {PATH}}?

25

Недавно я заметил следующее в моем профиле cygwin, точнее:

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

Что это означает? Почему не просто $ PATH? Это «если $ PATH существует, то добавить: $ PATH»? Моя цель - поменять порядок и поместить пути cygwin за путями Windows. В прошлом я бы

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

но это меня смущает. Может быть, я должен делать

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

добавить: в конце $ PATH?

tofutim
источник
1
Название вашего вопроса действительно перепутано с форматированием в боковой панели SE Hot Questions i.imgur.com/g6pPmzf.png
Брэд,

Ответы:

39

:+Является формой расширения параметра :

$ {параметр: + [слово]} : использовать альтернативное значение.

Если параметр не установлен или ноль, ноль должен быть заменен; в противном случае расширение слова (или пустая строка, если слово опущено) должно быть заменено.

Другими словами, если переменная $varопределена, echo ${var:+foo}она напечатает, fooа если нет, то напечатает пустую строку.

Второе :ничего особенного. Это символ, используемый в качестве разделителя в списке каталогов в $PATH. Итак, PATH="/usr/local/bin:/usr/bin${PATH:+:${PATH}}"это сокращенный способ написания:

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

Это просто умный трюк, чтобы избежать добавления лишнего, :когда $PATHон не установлен. Например:

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

Но если PATHне установлено:

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

:Сам по себе добавляет текущий каталог в $PATH. Использование PATH="/new/dir${PATH:+:$PATH}"избегает этого. Так что вы можете использовать, PATH="${PATH:+${PATH}:}/usr/local/bin:/usr/bin"если хотите, или использовать, PATH="$PATH:/usr/local/bin:/usr/bin"если хотите. Единственная разница в том, что первый может добавить дополнительный :, тем самым добавив ваш текущий каталог в ваш $PATH.

Тердон
источник
Является ли дополнительный :вред?
кот
4
@tac не совсем, он просто добавляет текущий каталог в ваш $PATH(см. ответ @ AndyB ). В некоторых ситуациях это может быть угрозой безопасности (например, злоумышленник загрузил деструктивный скрипт в ваш текущий каталог и назвал его lsили что-то в этом роде), но в большинстве случаев вы действительно не против. Фактически, некоторые системы PATHвсе равно добавляют текущий каталог в каталог по умолчанию.
Terdon
путь - это единственное место, где я бы предпочел, чтобы они cshобрабатывали путь, а не массив.
Hometoast
8

Вы правы, это означает, что «если $ PATH существует - и не равен нулю - тогда добавьте: $ PATH».

Вам нужно проверить, существует ли $ PATH, потому что вы не хотите добавлять начальное (или конечное) двоеточие, если $ PATH не определено. Имя каталога нулевой длины (нулевое) в пути, как в:/usr/local/bin:/usr/bin , или /usr/local/bin:/usr/bin:, или /usr/local/bin::/usr/bin, означает поиск в текущем каталоге .

Выдержка из man bash:

   PATH   ...
          A zero-length (null) directory name in the value of PATH indicates 
          the current directory.  A  null  directory name may appear as two 
          adjacent colons, or as an initial or trailing colon.
          ...

Это, вероятно, не то, что вы хотите сделать.

Следующие две строки делают то же самое:

PATH=":/bin"        # search current directory, then /bin
PATH=".:/bin"
AndyB
источник