$ PWD против pwd относительно переносимости
Я пишу оболочку script, которая анализирует путь к текущему рабочему каталогу (печатает как все базовые имена над текущим каталогом).
До сих пор я использовал переменную окружения PWD
для анализа пути, но мне интересно, если
- Я могу рассчитывать, что
PWD
всегда будет установлен
- чтобы дать тот же результат на каждой платформе
Возможно ли было бы лучше использовать оболочку PWD
? Мне нужно, чтобы этот script работал на максимально возможном количестве платформ, поэтому мне просто интересно...
Ответы
Ответ 1
POSIX требует, чтобы $PWD
устанавливался следующим образом:
PWD
Эта переменная должна представлять абсолютный путь к текущему рабочему каталогу. Он не должен содержать никаких компонентов, которые являются точками или точками. Значение устанавливается утилитой cd и утилитой sh во время инициализации.
Таким образом, вы можете полагаться на то, что установлено – но заметьте "... абсолютный путь...", а не абсолютный путь.
bash
(по крайней мере, последние версии) запоминает, какие символы вы следили при настройке $PWD
(и встроенного pwd
). command pwd
(т.е. внешняя команда) не будет. Таким образом, вы получите разные результаты, которые могут или не могут быть важны для вас. Используйте pwd -P
, если вам нужен путь без символических ссылок.
Обратите внимание, что в документации pwd
указано:
Если приложение устанавливает или отключает значение PWD, поведение pwd не указывается.
Итак, не делайте этого:)
Короче говоря, здесь нет победителя. Переменная среды будет находиться в оболочках POSIX, так же как и внешняя команда и, возможно, встроенная. Выберите тот, который наилучшим образом соответствует вашим потребностям, важно то, заботитесь ли вы о символических ссылках или нет.
Ответ 2
Из этой статьи форума $PWD vs `pwd`, который сравнивает AIX 4.2.1, AIX 6, Sparc Solaris 10 и Redhat 5 в этом отношении:
Первый показывает рабочий каталог с именами символических ссылок, тогда как последний показывает фактический путь.
Единственное несоответствие заключается в том, что внешняя команда находится в /usr/bin в большинстве систем и /bin в Redhat.
Ответ 3
Если вы знаете, что bash доступен и script выполняется с ним, PWD
безопасен.
Если в некоторых системах доступен только простой sh, используйте PWD
.
Ответ 4
Если бы это был я, я использовал бы pwd
, поскольку он является встроенным как для bash, так и для sh. Это не означает, что они работают одинаково во всех отношениях, но если вы вызываете его без параметров, это не имеет значения.
Ответ 5
Еще один момент, на который следует обратить внимание: подстановки команд, как правило, небезопасны при конце строки.
Это очевидно довольно надумано, но если вы действительно беспокоитесь о безопасной обработке ввода, вам следует использовать "$PWD"
. Смотрите, например:
$ my_dir=$'/tmp/trailing_newline\n'
$ mkdir -p "$my_dir"
$ cd "$my_dir"
$ pwd
/tmp/trailing_newline
$ printf "%q\n" "$(pwd)" "$PWD"
/tmp/trailing_newline
$'/tmp/trailing_newline\n'
$ cd "$(pwd)"
sh: cd: /tmp/trailing_newline: No such file or directory
$ cd "$PWD"
Можно обойти подстановку команд, но это ни в коем случае не красиво. Вы можете добавить завершающий символ и затем удалить его с расширением параметра:
$ pwd_guarded="$(pwd; printf '#')"
$ pwd_fixed="${pwd_guarded%$'\n'#}"
$ printf "%q\n" "$pwd_fixed"
$'/tmp/trailing_newline\n'
$ cd "$pwd_fixed"
Это особенно уродливо, потому что тогда вам также нужно удалить новую pwd
, которую добавляет pwd
, которая обычно удаляется подстановкой команд. Это становится полным беспорядком, если вы не прибегаете к конструкциям, отличным от POSIX, таким как $''
, поэтому, в основном, просто используйте "$PWD"
если вы заботитесь об этих вещах. Конечно, совершенно разумно просто не поддерживать завершающие символы новой строки в именах каталогов.