Разница между «CD -» и «CD ~ -»

56

Команда Bash

cd - 

печатает ранее использованный каталог и вносит в него изменения.

С другой стороны, команда Bash

cd ~-

напрямую переходит в ранее использовавшийся каталог, ничего не повторяя.

Это единственная разница? Какой вариант использования для каждой из команд?

dr01
источник
3
Я рекомендую вам не использовать эти хитрые вещи. Это твой мозг включен cd ~-.
ДепрессияДаниэль
10
@DepressedDaniel, даже если вы (не планируете) использовать хитрые вещи, все равно полезно понимать, что происходит за кулисами - понимание угловых случаев может позже вытащить вас из дыры при попытке отладить что-то другое.
anotherdave

Ответы:

81

Здесь есть две вещи. Во-первых, -один расширяется до вашего предыдущего каталога. Это объясняется в cdразделе man bash(выделение мое):

Аргумент аргумента -преобразуется в $ OLDPWD до попытки изменения каталога. Если используется непустое имя каталога из CDPATH, или если -это первый аргумент, и смена каталога прошла успешно, абсолютный путь нового рабочего каталога записывается в стандартный вывод. Возвращаемое значение равно true, если каталог был успешно изменен; ложь в противном случае.

Таким образом, простой cd -переместит вас обратно в ваш предыдущий каталог и выведет его имя. Другая команда описана в разделе «Расширение тильды»:

Если префикс тильды равен a ~+, значение переменной оболочки PWD заменяет префикс тильды. Если префикс тильды равен a ~-, подставляется значение переменной оболочки OLDPWD, если оно установлено. Если символы, следующие за тильдой в префиксе тильды, состоят из числа N, необязательно с префиксом a +или a -, префикс тильды заменяется соответствующим элементом из стека каталогов, как это будет показано встроенной командой dirs, вызываемой с помощью префикс тильды в качестве аргумента. Если символы, следующие за тильдой в префиксе тильды, состоят из числа без начального +или -, +предполагается.

Это может быть легче понять на примере:

$ pwd
/home/terdon
$ cd ~/foo
$ pwd
/home/terdon/foo
$ cd /etc
$ pwd
/etc
$ echo ~        ## prints $HOME
/home/terdon
$ echo ~+       ## prints $PWD
/etc
$ echo ~-       ## prints $OLDPWD
/home/terdon/foo

Так что, в общем, -означает «предыдущий каталог». Вот почему cd -само по себе вернет вас туда, где вы были.

Основное отличие заключается в том, что cd -характерно для cdвстроенного. Если вы попытаетесь echo -это просто напечатать -. ~-Является частью функциональности расширения тильды и ведет себя аналогично переменный. Вот почему вы можете echo ~-и получить что-то значимое. Вы также можете использовать его, cd ~-но вы также можете использовать его в любой другой команде. Например, cp ~-/* .который будет эквивалентенcp "$OLDPWD"/* .

Тердон
источник
1
set -xдля распечатки расширенной команды перед ее выполнением может быть полезно проиллюстрировать разницу (или может быть просто нечитабельно шумно, когда вы не делаете это самостоятельно по одному шагу за раз).
Питер Кордес
1
@terdon сегодня я узнал.
sitilge
Короче ... cd ~-/..работает, cd -/..нет!
Рэй Фосс
13

~-подлежит расширению тильды (см. man bash), так что cdнепосредственно видно предыдущее имя каталога. -не раскрывается оболочкой, cdвидит его напрямую и ведет себя так, как задокументировано:

Аргумент - эквивалентен $ OLDPWD. Если используется непустое имя каталога из CDPATH, или если - первый аргумент, и изменение каталога прошло успешно, абсолютный путь нового рабочего каталога записывается в стандартный вывод.

choroba
источник
4

TL; DR: cd -встроен cd, ~-является более поздним расширением ~[name], не относится к cd.

POSIX.1-2008 Shell & Utilities определяет cd -как особый случай, специфичный для cdкоманды :

Когда a -используется в качестве операнда, это должно быть эквивалентно команде:

cd "$OLDPWD" && pwd

который изменяется на предыдущий рабочий каталог, а затем записывает его имя.

~-Расширение будет расширено $OLDPWDдо того , как команда будет выполнена и может быть передано в качестве аргумента для любой команды, а не только cd. Это более позднее расширение в и .

Вышеупомянутый стандарт POSIX.1-2008 Shell & Utilities также содержит подробное объяснение расширения Tilde . Формулировка очень специфична и допускает ~-неопределенное поведение в рамках стандарта, где ~[name]ссылается на $HOMEто, [name]является ли пустая строка, или на домашний каталог пользователя, nameесли nameэто действительное имя пользователя.

Хенк Лангевельд
источник