Следует ли использовать кавычки в именах путей среды?
Я в процессе очистки всех моих конфигурационных файлов в попытке сделать их максимально читаемыми. Я искал руководство по стилю использования кавычек при экспорте путей, например, в :
export PATH="/users/me/path:$PATH"
vs
export PATH=/users/me/path:$PATH
Google стиль Shell руководство предлагает избегать кавычек для имен путей. Напротив, многие популярные репозитории dotfiles (например, Zach Holman's здесь) цитаты использовать. Есть ли ситуации, когда выгодно использовать кавычки в пути?
3 ответов
кончик шляпы к @gniourf_gniourf и @chepner за помощь.
tl; dr
чтобы быть в безопасности, двойная цитата: он будет работать во всех случаях, во всех POSIX-подобных оболочках.
если вы хотите добавить ~
путь, выборочно оставить ~/
без кавычек обеспечить ~
расширяется; например: export PATH=~/"bin:$PATH"
.
см. ниже за правила ~
расширение в назначениях переменных.
В качестве альтернативы просто используйте $HOME
внутри одной строки с двойными кавычками:export PATH="$HOME/bin:$PATH"
примечание: к bash
, ksh
и zsh
, но не для (в основном) строго совместимых с POSIX оболочек, таких как dash
; таким образом, когда вы нацелены /bin/sh
, вы должны дважды процитировать RHS export
.[1]
- двойной кавычки дополнительно, только если литерал часть вашего RHS (значение для назначения) не содержит ни пробелов, ни других метасимволов оболочки.
- ли значения переменные, на которые ссылается содержит пробелы / метасимволы или нет не вопрос - см. ниже.
- Еще Раз: Это тут с
sh
, когдаexport
используется, поэтому всегда двойная цитата там.
- Еще Раз: Это тут с
причина, по которой вы можете уйти без двойного цитирования в данном случае заключается в том, что переменная-задание утверждения в POSIX-подобных оболочках интерпретируют их RHS по-разному чем аргументы перешло к команды, как описано в 2.9.1 из POSIX spec:
в частности, хотя нач слово-расщепление is выполнено, применяется только к нерасширенные (raw) RHS (вот почему вы do нужно цитировать с пробелами / метасимволами в литералы), а не к его результаты.
этой относится только к подлинной заявления о присвоении форма
<name>=<value>
на все POSIX-подобные оболочки, то есть, если есть нет имени команды перед именем переменной; обратите внимание, что это включает задания начинаются команде для определения специальных переменных среды для нее, например,foo=$bar cmd ...
.-
задания в контексте других команд всегда следует дважды цитировать, чтобы быть сейф:
с
sh
(в (в основном) строго POSIX-совместимой оболочке, такой какdash
) назначение сexport
трактуется как обычная команда иfoo=$bar
часть рассматривается как 1-й аргумент доexport
builtin и поэтому обрабатывается как обычно (при условии разделения слов результат тоже).
(POSIX не указывает никаких других команд, включающих (явное) назначение переменных;declare
,typeset
иlocal
нестандартные расширения).-
bash
,ksh
,zsh
, в понятном отклонении от POSIX, расширьте логику назначения доexport foo=$bar
иtypeset/declare/local foo=$bar
как хорошо. Другими словами: наbash
,ksh
,zsh
,export/typeset/declare/local
команды рассматриваются как задания, так что цитирование не является строго необходимым.- возможно, удивительно,
dash
, который также решил реализовать non-POSIXlocal
builtin[2] , не распространяет на него логику присвоения; он согласуется с егоexport
поведение, однако.
- возможно, удивительно,
-
задания переданы
env
(например,env foo=$bar cmd ...
) также подлежат расширению в качестве аргумента команды и поэтому нуждаются в двойном цитировании-за исключениемzsh
.- это
env
действует иначеexport
вksh
иbash
в этом отношении связано с тем, чтоenv
это внешние утилиты, аexport
это shell builtin.
(zsh
'поведение s принципиально отличается от других снарядов, когда дело доходит до некотируемых ссылки на переменные).
- это
-
Тильда (
~
) расширение происходит следующим образом подлинной назначение заявления:- кроме
~
нужно без кавычек, как обычно, применяется лишь:- если весь RHS это
~
; например,:foo=~ # same as: foo="$HOME"
- иначе: только если и выполнены следующие условия:
- если
~
запускает строку или ей предшествует без кавычек:
- если
~
и без кавычек/
. - например,
foo=~/bin # same as foo="$HOME/bin"
foo=$foo:~/bin # same as foo="$foo:$HOME/bin"
- если
- если весь RHS это
- кроме
пример
этот пример демонстрирует, что в bash
, ksh
и zsh
вы можете уйти без двойное цитирование, даже при использовании export
, а I не рекомендую его.
#!/usr/bin/env bash
# or ksh or zsh - but NOT /bin/sh!
# Create env. variable with whitespace and other shell metacharacters
export FOO="b:c &|<> d"
# Extend the value - the double quotes here are optional, but ONLY
# because the literal part, 'a:`, contains no whitespace or other shell metacharacters.
# To be safe, DO double-quote the RHS.
export FOO=a:$foo # OK - $FOO now contains 'a:b:c &|<> d'
[1] как указывает @gniourf_gniourf: использование export
to изменить значение PATH
является необязательным, поскольку после того, как переменная помечена как экспортированная, вы можете использовать регулярное назначение (PATH=...
), чтобы изменить его значение.
Тем не менее, вы все еще можете выбрать использовать export
, чтобы сделать явным, что изменяемая переменная экспортируется.
[2] @gniourf_gniourf заявляет, что будущая версия стандарта POSIX может ввести local
builtin.
test 123
является допустимым именем пути в UNIX. Попробуй!--6-->
PATH=test 123
Он вернется:
123: command not found
или даже
export PATH=test 123
что вернет
bash export: `123': not a valid identifier
это ответ на твой вопрос?
честно говоря, я бы не стал следовать такому четвертой партии руководство по стилю. Хотя я удивлен, что даже Google рекламирует такие неправильные советы.
Я бы следуйте:
- http://www.tldp.org/LDP/Bash-Beginners-Guide/html/Bash-Beginners-Guide.html
- http://www.tldp.org/LDP/abs/html/
- https://www.gnu.org/software/bash/manual/bash.html
(осторожно расширенный)
я использовал эти ответы выше при настройке имен путей к среде в докере .env файл, и получил укус. Я помещаю это здесь для всех, кто ищет, как определить переменные среды для docker.
Docker compose считывает переменные среды из an .файл env, который существует в той же папке, что и docker compose, запускается, как указано здесь https://docs.docker.com/compose/env-file.
однако вместо обертывания значения в кавычки docker compose требуется переменная среды, определенная без кавычек, если кавычки не являются частью значения. Опять же, как указано в URL выше
нет специальной обработки кавычек (т. е. они будут часть VAL, вы были предупреждены;)
Я пытался установить NODE_PATH=./src
для абсолютных путей для работы в приложении react, развертываемом docker, но написанном как NODE_PATH="./src"
. Это предупреждение вытащило меня из 4-часовой кроличьей норы.