$ 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 в этом отношении:

  • нет разницы между $PWD и встроенным pwd,

  • нет разницы между встроенными pwd -P и /usr/bin/pwd.

Первый показывает рабочий каталог с именами символических ссылок, тогда как последний показывает фактический путь.

Единственное несоответствие заключается в том, что внешняя команда находится в /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" если вы заботитесь об этих вещах. Конечно, совершенно разумно просто не поддерживать завершающие символы новой строки в именах каталогов.