Делает кд. есть использование?

102

В одном из кратких руководств, за которым я следовал, cd .он бесполезен. При попытке воспроизвести проблему, показанную OP в рекурсии символьной ссылки, что делает ее «перезагрузкой»? Я также попробовал cd ., который показал тот же эффект, который описал OP (растущая $PWDпеременная), с которым можно бороться cd -P.

Это заставляет меня задуматься, есть ли случай, когда кто-то действительно хотел бы использовать cd . ?

Сергей Колодяжный
источник
20
У меня есть пользовательский .zshrc, который запускает различные проверки каталога при переключении каталога, например, одна из проверок заключается в автоматической активации / деактивации соответствующего virtualenv при перемещении каталогов. Иногда я могу запустить новую оболочку или что-то еще, и эти проверки не запускаются, и я обычно использую cd .для запуска этих проверок, потому что она короткая и простая. Хотя я думаю, что вы хотели, чтобы вопрос был для ванильной среды.
Ли Райан
29
Помимо (очевидного) влияния $PWD, cd .также вносятся изменения $OLDPWDв текущий каталог. Я (в настоящее время) понятия не имею, почему это может быть полезно, но ради полноты ...
Андреас Визе
5
Я не думаю, что я когда-либо нуждался cd ., хотя, видя ответы ниже, я мог бы в будущем, но я иногда использовал, pushd .когда я хотел быть в состоянии popdвернуться в этот каталог позже. например, при запуске сценария сборки, который делает configure, cd output...и make, и когда это будет сделано, я хочу вернуться к исходному каталогу. Вместо того, чтобы поддерживать свою собственную копию buildscript, которая отличается от того, что ожидают все остальные, я просто запускаю ее как pushd .; ./BuildScriptName.sh; popd, и это также дает мне свободу не popdиногда, а потом popdпозже.
3D1T0R
5
Не говоря уже о том, что "." и «..» не реализованы в самой команде cd, поэтому никто не собирается делать эту особенность, это просто комбинация вещей, которые не служат никакой реальной цели.
Дэвид С.
1
@ruakh Нет, внешние программы не должны влиять на среду выполнения оболочки. Это главным образом для соответствия POSIX, который требует, чтобы некоторые утилиты существовали вне оболочки, и оценки состояния выхода внешних команд. Вы можете прочитать о цели /bin/cdздесь unix.stackexchange.com/q/50058/85039
Сергей Колодяжный

Ответы:

158

Я думаю, что это переосмысление проблемы. cd .может быть не то, что можно было бы запустить вручную в обычном порядке, но это определенно то, что может возникнуть при программном выполнении (подумайте о любой ситуации, когда вы можете cdобратиться к каталогу, содержащему файл, путь которого указан пользователем ). Следовательно, он не должен иметь какое-то конкретное применение: пока он выполняет обычную семантику cd <some-path>, он полезен.

OLORIN
источник
12
Согласен, .должен рассматриваться как допустимый путь, указанный cdсинтаксисом просто отлично.
Сергей Колодяжный
18
Вы можете добавить следующий пример: Loops, как while IFS= read Dir; do cd "$Dir"; do_something; done < <(find . -type d). Во время его выполнения поиск производит .как путь, так что команда cd "$Dir"расширяется до cd .. Так что в скриптах это совершенно полезно.
Rexkogitans
5
Например, скрипт на самом деле выполняется cd ${path_to_directory}, но в какой-то момент оказывается, что каталог является текущим каталогом, и path_to_directory = .поэтому вам придется cd .работать на всякий случай.
Демис
4
Другими словами, его полезность заключается в том, что он делает ненужным дополнительный код ( ifпроверки и elseпредложения, любой вид специального регистра).
jpmc26
2
Так что это полезно в том смысле, что x + 0 или x * 1 полезны - конкретная операция сама по себе бесполезна, но это означает, что вы можете обрабатывать 0 и 1 так же, как любое другое значение, без необходимости рассматривать их как особый случай.
user32929
127

Путь к каталогу мог измениться с тех пор, как была выполнена последняя команда, и без cd .оболочек bash и ksh93 будет полагаться на логический рабочий каталог, описанный в сообщении, связанном с вопросом, поэтому вызов, вызывающий cd .проблему с getcwd()оболочкой, обеспечит системный вызов. текущий путь все еще действителен.

Шаги для воспроизведения в Bash:

  1. В терминальной вкладке вопрос mkdir ./dir_no_1; cd ./dir_no_1
  2. В другом терминале проблема с вкладкой mv dir_no_1 dir_no_2
  3. В первой вкладке терминала выдают echo $PWDи pwd. Обратите внимание, что каталог был переименован извне; среда оболочки не была обновлена.
  4. Issue cd .; pwd; echo $PWD. Обратите внимание, что значение было обновлено.

ksh93, однако, не обновляет информацию об окружающей среде, поэтому cd .в ksh93 может фактически оказаться бесполезным. В /bin/dashUbuntu и других системах на основе Debian cd .возвращает dash: 3: cd: can't cd to .ошибку, однако cd -P .работает (в отличие от ksh93).

Сергей Колодяжный
источник
22
Полезно знать: я добавлю это в свой список бесполезной информации. ^^)
jayooin
12
@jayooin Рад, что смог внести свой вклад в список;)
Сергей Колодяжный
8
Я думаю, что вы можете сделать mv ../dir_no_1 ../dir_no_2в том же терминале / Bash.
Ctrl-Alt-Delor
3
@ ctrl-alt-delor Подтверждено, работает :)
Сергей Колодяжный
1
@ymbirtt В большинстве оболочек pwdфактически является встроенным, однако вызов /bin/pwdне влияет на среду оболочки - внешние утилиты в целом не влияют на среду оболочки. Причина /bin/cdи /bin/pwdсуществует, среди прочего, для соответствия POSIX. Там очень хорошая дискуссия о внешнем диске , некоторые из которых , вероятно , относится и к /bin/pwdа
Сергей Kolodyazhnyy
55

Другой вариант cd .использования: когда каталог, в котором вы сейчас находитесь, был удален, а затем снова создан. Попробуйте попробовать следующее -

  1. Создать каталог temp
  2. cd temp а затем сделать ls
  3. Откройте другой терминал и удалите, а затем заново создайте этот каталог temp
  4. Вернитесь из первого терминала, попробуйте выполнить команду ls. Это приведет к ошибке -ls: cannot open directory .: Stale file handle
  5. cd . а затем делает ls работает нормально
Сахил Агарвал
источник
3
Это не всегда работает. В dash, например, вы получите: cd: can't cd to .Теперь, когда я смотрю на это, это уже упоминалось в ответе Сергея (перемещение, удаление / воссоздание - по сути, то же самое: каталог, в котором вы находитесь, больше не является тем, что был в оригинале путь)
Олорин
12
Я часто использую это для тестирования удаленных приложений. Каталог, в котором я сейчас нахожусь, будет удален, а затем воссоздан с помощью некоторой автоматизации, и мне нужно будет выполнить cd .команду, чтобы перейти в новый каталог с тем же именем.
HP Williams
2
Я использую cd .все время, когда у меня есть оболочка, текущий рабочий каталог которой был смонтирован с помощью sshfs, но сессия ssh была закрыта и снова открыта.
Джеймсдлин
4
В таком случае я делаю "CD $ PWD". Другие варианты могут работать, но этот явно выражает намерение: извлечь то, что должно быть моим текущим путем (т. Е. Прочитать содержимое PWDпеременной среды), затем пройти иерархию файловой системы от корня до каталога, который оказывается доступным через этот путь, будь то на самом деле тот же каталог или нет. Это точно соответствует случаю использования в этом ответе.
Стефан Гурихон
3
Я действительно удивлен, даже потрясен, что это cd .работает, когда каталог не связан, и новый каталог создается по тому же пути файловой системы. Текущий рабочий каталог был не связан, и, по-видимому, как часть этого, у него больше нет записи .или .., и даже если он есть, .запись должна продолжать указывать на себя. Похоже, что оболочка или ядро ​​выполняет команду cd, основываясь на том, какое имя пути к каталогу было, а не просто на доступе к .записи. Кто-нибудь может подтвердить это поведение?
Адриан Пронк
36

Вы можете $OLDPWDбыстро очистить cd ., если должен быть случай, когда вы не хотите, чтобы это указывало на что-то «интересное». Это также повлияет cd -.

unperson325680
источник
16

Программно это полезно как неоперативный. Рассмотрим путь, предоставленный внешним вводом.

read -p "Path to file: " p
dirn=$(dirname "$p")
file=$(basename "$p")
echo "dirn=$dirn, file=$file"
cd "$dirn"
ls -ld "$file"

С путем , такими как «fred.txt» каталог будет ., что приведет кcd .

roaima
источник
1
Полезно, чтобы он не выдавал ошибку, если вы уже находитесь в каталоге, к которому вы переходите, но я бы не сказал, что он полезен как неоперативный.
Капитан Мэн
2
@CaptainMan, который не выдает ошибку, если вы уже находитесь в каталоге, является (по сути) неактивным. Команда dirnameгенерирует, .где это необходимо, чтобы избежать взлома кода, который ожидает разбить путь.
Ройма
15

Это часто случается, если вам приходилось работать с плохим USB-кабелем. После того, как устройство будет отключено и снова подключено и автоматически подключено к тому же каталогу, вы должны будете снова использовать cd .его для работы.

user23013
источник
1
Не будет ли это зависеть от того, какое устройство, как к нему обращаются, его файловая система, ОС и т. Д.?
Gidds
ОС, может быть. Маловероятно, что файловая система уместна, если ядро ​​может найти способ размонтировать ее во время использования. В любом случае, команда имеет свое применение в совершенно правильной ситуации.
user23013
11

Обратите внимание, что "." это правильный способ указать имя файла, который открыт как текущий рабочий каталог любого процесса (включая, конечно, процесс оболочки), и "." всегда является допустимым именем файла во всех без исключения каталогах, включая текущий рабочий каталог. Имя .может не являться допустимым именем для файла для данного экземпляра процесса, если, скажем, текущий текущий рабочий каталог был удален (или стал «плохим», например устаревший дескриптор NFS), но это допустимое имя файла, который гарантированно существует в каждом допустимом каталоге.

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

Является ли cd .это полезно или нет , зависит от реализации оболочки. Как уже упоминалось, это может быть полезно, если оболочка сбрасывает свое внутреннее представление о полном пути к текущему рабочему каталогу после вызова базового chdirсистемного вызова, например, если базовый каталог (или некоторый его родитель) был переименован.

По крайней мере , некоторые оболочки которых я знаю ( /bin/shна FreeBSD и NetBSD) будет конвертировать cd ""в cd ., который , возможно , может быть описана функцией поддержки программного использования в сценарии оболочки , где переменный может быть использован в качестве параметра (т.е. преобразование пустой подстановки переменной в " «ничего не делать»), хотя история коммитов FreeBSD гласит, что изменение было напрямую связано с добавлением поддержки POSIX для предотвращения сбоя chdir(""), который должен произойти из-за мандатов POSIX.

Некоторые другие оболочки заменят .все, что они сохранили, как полное имя пути к своему текущему рабочему каталогу, и, таким образом, для них это может позволить поведение, упомянутое в ответе Сахила Агарвала .

Грег А. Вудс
источник
4

Я использовал эту команду только сегодня, когда перебазировал ветку, над которой я работал, в Git из каталога, который был сначала создан в этой же ветке. Ребаз прошел нормально но потом git statusвыкинул ошибку. После cd .все было нормально.

(Кстати, я работал в MobaXterm на Windows. На всякий случай, если вы пытаетесь воспроизвести это. Это может не произойти в других системах.)


Я также использовал эту команду в каталогах, которые обновляются автоматическим процессом, который перемещает в сторону старый каталог и заменяет его новым (поэтому он максимально приближен к атомарному). Не обычная ситуация, но cd .это именно то, что нужно.


Прочитав этот отличный ответ от Стефана Шазеля:

Теперь я понимаю, что приведенные выше варианты использования работают только потому, что я использую bash, что cd .эквивалентно cd "$PWD". Я настоятельно рекомендую прочитать связанный ответ.

Wildcard
источник
1

Я использую, cd .чтобы перезапустить материал, которым я перегружен cdчерез bashфункцию.

Из моего ~/.bashrc:

# from the "xttitle(1)" man page - put info in window title
update_title()
{
    [[ $TERM = xterm ]] || [[ $TERM = xterm-color ]]  && xttitle "[$$] ${USER}@${HOSTNAME}:$PWD"
}

cd()
{
    [[ -z "$*" ]] && builtin cd $HOME
    [[ -n "$*" ]] && builtin cd "$*"
    update_title
}
waltinator
источник
0

РЕДАКТИРОВАТЬ: Это уже было предложено Sahil ранее.

Это полезно, если вы находитесь в папке, которая была удалена и воссоздана другим процессом. Например, предполагая два терминальных сеанса $1и $2:

$1 mkdir d
$1 cd d
$1 touch f

$2 rm -rf /path/to/d # delete the folder where $1 is in ...
$2 mkdir /path/to/d # ... and recreate it

$1 touch g # cannot create file g because current dir doesn't exist anymore
touch: cannot touch ‘g’: Stale file handle
$1 cd . # go to the newly created dir (same path)
$1 touch g # works fine now

Я не уверен, где именно (OS, SHELL, ...?) Коренная причина этого поведения.

Рольф
источник
Это уже упоминалось в других ответах.
Кусалананда
-8

Нет, это не имеет смысла. Ни в сценарии, он просто ничего не делает.

Federico
источник
2
В зависимости от оболочки, он будет сброшен $PWDи, возможно, вызовет другие функции оболочки, если пользователь предоставит свою собственную cdфункцию или псевдоним для перегрузки встроенного cd. Это также проверило бы, что текущий каталог все еще действителен и что текущее использование имеет разрешение быть там.
Кусалананда
1) конечно, мы говорим не о возможных пользовательских псевдонимах "cd", а о стандартной сборке 2) как может использоваться текущее использование, если у него нет разрешения? Проще говоря, я просто говорю, что в реальном мире нет причин использовать его по моему мнению.
Федерико
1
1) не так ли? 2) Реальный мир не прост, и Unix является многопользовательской операционной системой. Пользователь может изменить разрешения для каталогов, и, если сценарий или интерактивная оболочка другого пользователя получит этот каталог (или его подкаталог) в качестве своего рабочего каталога, cd .будет жаловаться.
Кусалананда
4
Федерико, согласно правилам сайта и моим личным правилам, я должен понизить ваш ответ. Тем не менее, вы новичок. Добро пожаловать! Пожалуйста, ознакомьтесь с некоторыми другими ответами . После этого, если вы считаете, что ваш ответ неверен, удалите его. Пожалуйста, с удовольствием дайте другие ответы на этот вопрос и другие.
Давелоял
2
Особенно в сценариях, иногда «ничего не делает» именно то, что нужно.
Мэтью Наджмон