Следует ли использовать кавычки в именах путей среды?
Я в процессе очистки всех моих конфигурационных файлов в попытке сделать их максимально читаемыми. Я искал руководство по стилю использования кавычек при экспорте путей, например, в :
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-й аргумент доexportbuiltin и поэтому обрабатывается как обычно (при условии разделения слов результат тоже).
(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-POSIXlocalbuiltin[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-часовой кроличьей норы.