Лучше использовать $ (pwd) или $ PWD?

35

Я столкнулся BASEDIR=$(pwd)в сценарии.

Есть ли какие-либо преимущества или недостатки по сравнению с использованием BASEDIR="$PWD", которые $PWDмогут быть перезаписаны?

Minix
источник
3
некоторая информация на unix.stackexchange.com/a/79621
Стефан
@ StéphaneChazelas Очень интересно пишите. Я только на полпути и буду продолжать, но, насколько я понял, лучше использовать $(pwd), потому что $PWDв определенных обстоятельствах может устареть.
Minix
2
только в некоторых оболочках (не в bash, dash, zsh или ksh93, например) pwdпотенциально вы получите менее устаревшую информацию, чем $PWDв некоторых угловых случаях. $(pwd)с другой стороны, не работает, если текущий каталог оканчивается символами новой строки, означает разветвление процесса (кроме ksh93) и использование дополнительных ресурсов. По моему мнению , использование $PWDв $(pwd -P)это не стоит использовать $(pwd).
Стефан Шазелас
1
внизу упоминается Стефан с помощью cd -P -- "$dir". если есть какие-либо сомнения в ценности, $PWDвы всегда можете cd -P .сначала. это также может быть полезным в том смысле, что вы также получаете то, что $PWDбыло до этого, $OLDPWDи поэтому можете сравнить их потом - и следующая cd ...; cd -последовательность наверняка вернет вас туда, где вы сейчас находитесь.
mikeserv

Ответы:

41

Если bash встретится, $(pwd)он выполнит команду pwd и заменит $(pwd)выходные данные этой команды. $PWDпеременная, которая почти всегда установлена. PWD давно является встроенной командой оболочки.

Так что $PWDпроизойдет сбой, если эта переменная не установлена, и $(pwd)произойдет сбой, если вы используете оболочку, которая не поддерживает $()конструкцию, что, как мне кажется, довольно часто. Так что я бы использовал $PWD.

Как и у каждого ботаника, у меня есть свой учебник по написанию сценариев оболочки

Торстен Стэрк
источник
6
У меня сложилось впечатление, что `command`синтаксис был нежелателен и $(command)должен быть предпочтительным. Насколько я знаю, последний совместим с POSIX, но я не уверен на 100%.
Minix
6
@Minix $()Действительно определяется POSIX, поэтому за пределами предварительной версии POSIX, /bin/shдоступной в Solaris 10 и более ранних версиях и cshпроизводных оболочках, я сомневаюсь, что во многих других общедоступных оболочках эта функция отсутствует.
Jlliagre
@Minix: Вот недавний вопрос на этом сайте, который иллюстрирует одну проблему с использованием обратных $()
галочек
правильно, вместо $ () вы можете использовать обратные пометки, но это не будет каскадно, поэтому я не упомянул об этом
Thorsten Staerk
1
Хорошая миникарта на вашем уроке ....
kbtzr
6

Также следует упомянуть, что $PWDжелательно из-за его производительности. Как переменная оболочки, она может быть решена практически мгновенно. $(pwd)немного более запутанным. Если вы проверяете man 1 bulitinсистему с помощью Bash, вы увидите, что pwdэто встроенная команда, которая может заставить вас поверить, что она будет такой же быстрой, как и доступ к переменной. Однако $()конструкция всегда запускает новый подоболочек (новый процесс) для запуска своего содержимого, независимо от того, что находится внутри. То же самое касается спины. Действительно, когда я оцениваю это:

echo 'Benchmarking $(pwd)...'
time (for i in {1..1000}; do echo $(pwd) > /dev/null; done)
echo 'Benchmarking $PWD...'
time (for i in {1..1000}; do echo $PWD > /dev/null; done)

Я получаю 1,52 секунды за $(pwd)звонок и 0,018 секунды за $PWD. По возможности следует избегать ненужного запуска подоболочек, а также любых других посторонних процессов. Они намного дороже, чем вызовы функций, к которым вы можете привыкнуть на других языках.

markasoftware
источник
Это интересный пример, но я не знаю, обеспокоен ли я производительностью моих сценариев оболочки. Мне также интересно, как изменится производительность, если pwd изменится между запросами.
Minix
@Minix Я изменил свой скрипт, чтобы иметь тело цикла echo $PWD; pushd ..; echo $PWD; popd(с дополнительным >/dev/nullпосле каждого оператора), и это занимает 0,05 секунды. Затем я удалил операторы echo (только pushd / popd), и это заняло 0,03. Таким образом, время за echo $PWDвсе еще было 0,01 секунды или около того. Я сделал что-то подобное с $(pwd), и это заняло 2,2 секунды для каждого цикла, так что 1,1 секунды на $(pwd)вызов.
markasoftware
Не слишком требователен, но я могу себе представить, что вычисление, которое должно $PWDбыло бы быть заменено, было бы выполнено в фоновом режиме до оценки операторов echo. Но очевидно, что доступ $PWDпо-прежнему значительно быстрее, поэтому, если совместимость не является проблемой, это определенно является причиной выбора одного над другим. Спасибо за тщательную работу по тестированию. :)
Minix