Tut cd. Verwendung haben?

102

In einem der Tutorials, die ich verfolgt habe, wurde kurz gesagt, dass cd .es keine Verwendung hat. Wenn versucht wird, das von OP in der Rekursion symbolischer Verknüpfungen angezeigte Problem zu replizieren, warum wird es dann zurückgesetzt? Ich habe auch versucht cd ., den gleichen Effekt OP zu zeigen (wachsende $PWDVariable), mit dem entgegengewirkt werden kann cd -P.

Das lässt mich wundern, gibt es einen Fall, in dem man tatsächlich nutzen möchte cd . ?

Sergiy Kolodyazhnyy
quelle
20
Ich habe eine benutzerdefinierte .zshrc-Datei, die beim Wechseln des Verzeichnisses verschiedene Überprüfungen des Verzeichnisses ausführt. Beispielsweise besteht eine der Überprüfungen darin, beim Verschieben von Verzeichnissen automatisch eine übereinstimmende virtuelle Umgebung zu aktivieren / deaktivieren. Gelegentlich starte ich möglicherweise eine neue Shell oder was auch immer, und diese Überprüfungen werden nicht ausgeführt. Normalerweise löse ich cd .diese Überprüfungen aus, weil sie kurz und einfach sind. Obwohl ich denke, dass Sie die Frage für eine Vanille-Umgebung gedacht haben.
Lie Ryan
29
Neben der (offensichtlich) Wirkung auf $PWD, cd .ändert sich auch $OLDPWDin das aktuelle Verzeichnis. Ich habe (derzeit) keine Ahnung, warum dies nützlich sein könnte, aber der Vollständigkeit halber ...
Andreas Wiese
5
Ich glaube nicht, dass ich jemals gebraucht habe cd ., obwohl ich die Antworten unten gesehen habe, vielleicht in der Zukunft, aber ich habe sie gelegentlich verwendet, pushd .als ich später in der Lage sein wollte, zu popddiesem Verzeichnis zurückzukehren. Wenn Sie beispielsweise ein Build-Skript ausführen configure, das cd output...und ausführt , und makewenn dies abgeschlossen ist, möchte ich zum ursprünglichen Verzeichnis zurückkehren. Anstatt meine eigene Kopie des Buildskripts zu pflegen, die sich von den Erwartungen aller anderen unterscheidet, führe ich es einfach so aus pushd .; ./BuildScriptName.sh; popd, und dies gibt mir auch die Freiheit, nicht popdmanchmal und dann popdspäter stattdessen.
3D1T0R
5
Ganz zu schweigen von dem '.' und '..' sind nicht im cd-Befehl selbst implementiert, daher hat niemand die Absicht, diese spezielle Funktion zu implementieren. Es handelt sich lediglich um eine Kombination von Dingen, die keinem wirklichen Zweck dienen.
David S
1
@ruakh Nein, externe Programme sollten die Shell-Ausführungsumgebung nicht beeinflussen. Hauptsächlich für die POSIX-Konformität, bei der einige Dienstprogramme außerhalb der Shell vorhanden sein müssen und der Exit-Status externer Befehle ausgewertet werden muss. Sie können über den Zweck von /bin/cdhier lesen unix.stackexchange.com/q/50058/85039
Sergiy Kolodyazhnyy

Antworten:

158

Ich denke, das überdenkt das Problem. cd .Es kann sein, dass dies nicht etwas ist, das man im normalen Ablauf manuell ausführen würde, aber es ist definitiv etwas, das bei der programmgesteuerten Ausführung auftreten kann (denken Sie an jede Situation, in der Sie möglicherweise cdzu dem Verzeichnis gelangen, das eine Datei enthält, deren Pfad vom Benutzer angegeben wird ). Daher muss es nicht speziell verwendet werden: Solange es die gewohnte Semantik von erfüllt cd <some-path>, ist es nützlich.

Olorin
quelle
12
Einverstanden, .sollte als gültiger Pfad durch die cdSyntax genau richtig behandelt werden.
Sergiy Kolodyazhnyy
18
Sie können das folgende Beispiel hinzufügen: Schleifen wie while IFS= read Dir; do cd "$Dir"; do_something; done < <(find . -type d). Find wird .im Verlauf als Pfad erzeugt , so dass der Befehl zu cd "$Dir"expandiert cd .. In Skripten ist es also vollkommen nützlich.
rexkogitans
5
Beispielsweise wird ein Skript tatsächlich ausgeführt cd ${path_to_directory}, aber irgendwann stellt sich heraus, dass es sich bei dem Verzeichnis um das aktuelle Verzeichnis handelt. path_to_directory = .Sie müssten also cd .nur für alle Fälle arbeiten.
Demis
4
Mit anderen Worten, seine Nützlichkeit besteht darin, dass es zusätzlichen Code ( ifPrüfungen und elseKlauseln, jede Art von Sondergehäuse) unnötig macht.
jpmc26
2
Es ist also nützlich in dem Sinne, dass x + 0 oder x * 1 nützlich sind - die spezifische Operation ist an sich nicht nützlich, aber es bedeutet, dass Sie 0 und 1 wie jeden anderen Wert behandeln können, ohne sie als solche behandeln zu müssen ein besonderer Fall.
User32929
127

Der Pfad des Verzeichnisses könnte sich geändert haben, seit der letzte Befehl ausgeführt wurde, und ohne cd .die Shells bash und ksh93 wird das in dem in der Frage verlinkten Beitrag beschriebene logische Arbeitsverzeichnis verwendet. Wenn Sie also cd .das Shell-Problem aufrufen , getcwd()wird Ihr Syscall sichergestellt Der aktuelle Pfad ist weiterhin gültig.

Schritte zum Reproduzieren in Bash:

  1. In einer Terminal-Registerkarte Problem mkdir ./dir_no_1; cd ./dir_no_1
  2. In einem anderen Terminal-Tab Problem mv dir_no_1 dir_no_2
  3. In der ersten Registerkarte Terminal Ausgabe echo $PWDund pwd. Beachten Sie, dass das Verzeichnis extern umbenannt wurde. Die Umgebung der Shell wurde nicht aktualisiert.
  4. Ausgabe cd .; pwd; echo $PWD. Beachten Sie, dass der Wert aktualisiert wurde.

ksh93 aktualisiert jedoch nicht die Umgebungsinformationen, so dass cd .ksh93 in der Tat unbrauchbar sein kann. In /bin/dashauf Ubuntu und andere Debian-basierten Systemen cd .gibt dash: 3: cd: can't cd to .Fehler, jedoch cd -P .funktioniert ( im Gegensatz zu in ksh93).

Sergiy Kolodyazhnyy
quelle
22
Gut zu wissen: Ich werde das zu meiner Liste der nutzlosen Informationen hinzufügen. ^^)
Jayooin
12
@jayooin Glad konnte ich zu der Liste beitragen;)
Sergiy Kolodyazhnyy
8
Ich denke, Sie können mv ../dir_no_1 ../dir_no_2im gleichen Terminal / Bash tun .
Strg-Alt-Delor
3
@ ctrl-alt-delor Bestätigt, funktioniert :)
Sergiy Kolodyazhnyy
1
@ymbirtt In den meisten Shells pwdist in der Tat ein eingebautes, jedoch hat das Aufrufen /bin/pwdkeine Auswirkung auf die Umgebung der Shell - externe Dienstprogramme beeinflussen die Shell-Umgebung im Allgemeinen nicht. Der Grund, warum /bin/cdund /bin/pwdvorhanden ist, liegt unter anderem in der POSIX-Konformität. Es gibt eine gute Diskussion über externe CD von denen einige wahrscheinlich gilt /bin/pwdauch
Sergiy Kolodyazhnyy
55

Ein weiterer Anwendungsfall von cd .wäre, wenn das Verzeichnis, in dem Sie sich gerade befinden, gelöscht und dann erneut erstellt wurde. Versuchen Sie Folgendes:

  1. Erstellen Sie ein Verzeichnis temp
  2. cd temp und dann mach ein ls
  3. Öffnen Sie ein anderes Terminal, löschen Sie das Verzeichnis und erstellen Sie es neu temp
  4. Versuchen Sie, vom ersten Terminal aus ein ls zu machen. Dies würde zu einem Fehler führen -ls: cannot open directory .: Stale file handle
  5. cd . und dann funktioniert ein ls gut
Sahil Agarwal
quelle
3
Das funktioniert nicht immer. Im Bindestrich erhalten Sie zum Beispiel: cd: can't cd to .Jetzt, wo ich es mir ansehe, wird dies bereits in Sergijs Antwort erwähnt (Verschieben, Löschen / Neuerstellen - im Wesentlichen dasselbe: Das Verzeichnis, in dem Sie sich befinden, ist nicht mehr das, was sich im Original befand Weg)
Olorin
12
Ich benutze diese viel testen Remote-Bereitstellungen. Das Verzeichnis, in dem ich mich befinde, wird gelöscht und dann durch eine gewisse Automatisierung neu erstellt, und ich muss es ausgeben cd ., um in das neue Verzeichnis mit demselben Namen zu wechseln.
HP Williams
2
Ich benutze die cd .ganze Zeit, wenn ich eine Shell habe, deren aktuelles Arbeitsverzeichnis mit sshfs gemountet wurde, aber die ssh-Sitzung geschlossen und wieder geöffnet wurde.
Jamesdlin
4
In einem solchen Fall mache ich "cd $ PWD". Andere Varianten mögen funktionieren, aber diese drücken die Absicht klar aus: extrahieren Sie meinen aktuellen Pfad (dh lesen Sie den Inhalt der PWDUmgebungsvariablen) und durchlaufen Sie die Dateisystemhierarchie vom Stammverzeichnis bis zu einem Verzeichnis, über das zufällig erreichbar ist dieser Pfad, ob es sich tatsächlich um das gleiche Verzeichnis handelt oder nicht. Dies passt genau zum Anwendungsfall in dieser Antwort.
Stéphane Gourichon
3
Ich bin wirklich überrascht und schockiert, dass dies cd .funktioniert, wenn die Verknüpfung des Verzeichnisses aufgehoben wurde und ein neues, anderes Verzeichnis unter demselben Dateisystempfad erstellt wird. Das aktuelle Arbeitsverzeichnis wurde nicht verlinkt und hat vermutlich als Teil davon keinen .oder ..-Eintrag mehr, und selbst wenn dies der .Fall ist, sollte der Eintrag weiterhin auf sich selbst verweisen. Es sieht so aus, als würde die Shell oder der Kernel den Befehl cd basierend auf dem Verzeichnispfadnamen ausführen, anstatt einfach auf den .Eintrag zuzugreifen . Kann jemand dieses Verhalten bestätigen?
Adrian Pronk
36

Sie können $OLDPWDmit einem kurzen klarstellen cd ., ob es einen Fall geben soll, in dem Sie nicht wollen, dass er irgendwo "interessant" ist. Es wird auch beeinflussen cd -.

unperson325680
quelle
16

Programmatisch ist es als No-Op nützlich. Betrachten Sie einen Pfad, der von einer externen Eingabe bereitgestellt wird.

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

Bei einem Pfad wie "fred.txt" wird das Verzeichnis .zucd .

Roaima
quelle
1
Es ist nützlich, dass es keinen Fehler auslöst, wenn Sie sich bereits in dem Verzeichnis befinden, zu dem Sie navigieren, aber ich würde nicht sagen, dass es als No-Op nützlich ist.
Captain Man
2
@CaptainMan wirft keinen Fehler, wenn Sie bereits im Verzeichnis sind, ist (effektiv) ein No-Op. Der dirnameBefehl wird .bei Bedarf generiert , um zu vermeiden, dass Code beschädigt wird, der einen Pfad aufteilen kann.
Roaima
15

Dies ist häufig der Fall, wenn Sie mit einem fehlerhaften USB-Kabel arbeiten mussten. Nachdem ein Gerät getrennt und wieder verbunden wurde und automatisch in dasselbe Verzeichnis gemountet wurde, müssen Sie verwenden cd ., damit es wieder funktioniert.

user23013
quelle
1
Hängt das nicht davon ab, auf welche Art von Gerät, auf welche Weise darauf zugegriffen wird, auf welches Dateisystem, auf welches Betriebssystem usw.?
gidds
OS vielleicht. Es ist unwahrscheinlich, dass das Dateisystem relevant ist, solange der Kernel seinen Weg findet, es während seiner Verwendung zu entfernen. In jedem Fall kann der Befehl in genau der richtigen Situation verwendet werden.
User23013
11

Beachten Sie, dass "." ist die richtige Methode, um den Namen der Datei anzugeben, die als aktuelles Arbeitsverzeichnis eines Prozesses (einschließlich natürlich eines Shell-Prozesses) geöffnet ist, und "." ist immer ein gültiger Name einer Datei in allen Verzeichnissen, einschließlich des aktuellen Arbeitsverzeichnisses. Der Name ist .möglicherweise kein gültiger Name für eine Datei für eine bestimmte Instanz eines Prozesses, wenn beispielsweise das zugrunde liegende aktuelle Arbeitsverzeichnis entfernt wurde (oder "fehlerhaft" geworden ist, z. B. ein veralteter NFS-Punkt), es ist jedoch ein gültiger Name einer Datei, die garantiert in jedem gültigen Verzeichnis existiert.

So . muss ein gültiges Argument für jeden Befehl sein, der den Namen eines Verzeichnisses akzeptiert, und damit in der Standard - Shell cd .muss ein gültiger Befehl sein.

Ob dies cd .sinnvoll ist oder nicht, hängt von der Shell-Implementierung ab. Wie bereits erwähnt, kann es nützlich sein, wenn die Shell nach dem Aufrufen des zugrunde liegenden chdirSystemaufrufs ihre interne Idee des vollständigen Pfadnamens des aktuellen Arbeitsverzeichnisses zurücksetzt , z. B. wenn das zugrunde liegende Verzeichnis (oder ein übergeordnetes Verzeichnis davon) umbenannt wurde.

Zumindest einige der mir bekannten Shells ( /bin/shunter FreeBSD und NetBSD) konvertieren cd ""in cd ., was wohl eine Funktion zur Unterstützung der programmgesteuerten Verwendung in einem Shell-Skript sein kann, bei der eine Variable als Parameter verwendet werden kann (dh das Konvertieren einer leeren Variablensubstitution in eine " "nichts tun"), obwohl der FreeBSD-Commit-Verlauf besagt, dass die Änderung direkt auf das Hinzufügen von POSIX-Unterstützung zurückzuführen ist, um einen Fehler zu verhindern chdir(""), bei dem POSIX-Mandate fehlschlagen müssen.

Einige andere Shells ersetzen das, .was sie als vollständig qualifizierten Pfadnamen zu ihrem aktuellen Arbeitsverzeichnis gespeichert haben, und daher kann dies für sie das in Sahil Agarwals Antwort erwähnte Verhalten zulassen .

Greg A. Woods
quelle
4

Ich habe diesen Befehl erst heute verwendet, als ich den Zweig, an dem ich in Git gearbeitet habe, von einem Verzeichnis aus neu basierte, das zuerst auf demselben Zweig erstellt wurde. Der Rebase ging gut, aber danach git statuswarf einen Fehler. Nachdem cd .alles normal war.

(Ich habe übrigens in MobaXterm unter Windows gearbeitet. Nur für den Fall, dass Sie versuchen, dies zu reproduzieren. Auf anderen Systemen ist dies möglicherweise nicht möglich.)


Ich habe diesen Befehl auch in Verzeichnissen verwendet, die durch einen automatisierten Prozess aktualisiert werden, der das alte Verzeichnis beiseite schiebt und durch ein neues ersetzt (so dass es möglichst atomar ist). Keine alltägliche Situation, aber cd .genau das, was benötigt wird.


Nach dem Lesen dieser ausgezeichneten Antwort von Stephane Chazelas:

Ich verstehe jetzt, dass meine oben genannten Anwendungsfälle nur funktionieren, weil ich sie verwende bash, in denen sie cd .äquivalent sind zu cd "$PWD". Ich empfehle dringend, die verlinkte Antwort zu lesen.

Platzhalter
quelle
1

Ich benutze es, cd .um das Zeug, mit dem ich überladen bin, cdüber eine bashFunktion erneut auszuführen .

Von meinem ~/.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
quelle
0

EDIT: Dies wurde von Sahil bereits zuvor vorgeschlagen .

Dies ist nützlich, wenn Sie sich in einem Ordner befinden, der von einem anderen Prozess gelöscht und neu erstellt wurde. Angenommen, die beiden Terminalsitzungen $1und $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

Ich bin nicht sicher, ob genau (OS, SHELL, ...?) Die Ursache für dieses Verhalten ist.

Rolf
quelle
Dies wurde bereits in anderen Antworten erwähnt.
Kusalananda
-8

Nein, es hat keinen Sinn. Weder in der Skripterstellung tut es einfach nichts.

Federico
quelle
2
Abhängig von der Shell würde sie zurückgesetzt $PWDund möglicherweise andere Shell-Funktionen aufrufen, wenn der Benutzer eine eigene cdFunktion oder einen eigenen Alias ​​angegeben hat, um das eingebaute System zu überlasten cd. Es wird auch überprüft, ob das aktuelle Verzeichnis noch gültig ist und ob die aktuelle Verwendung die Berechtigung hat, dort zu sein.
Kusalananda
1) Natürlich sprechen wir nicht über mögliche benutzerdefinierte Aliase von "cd", sondern über den Standard-Build 2) Wie kann die aktuelle Verwendung dort sein, wenn sie keine Erlaubnis hat? Um es einfach zu machen, sage ich nur, dass es in der realen Welt meiner Meinung nach keinen Grund gibt, es zu benutzen.
Federico
1
1) Sind wir nicht? 2) Die reale Welt ist nicht einfach, und Unix ist ein Betriebssystem für mehrere Benutzer. Ein Benutzer kann Berechtigungen für Verzeichnisse ändern und cd .sich beschweren , wenn das Skript oder die interaktive Shell eines anderen Benutzers dieses Verzeichnis (oder ein Unterverzeichnis davon) als Arbeitsverzeichnis hat .
Kusalananda
4
Federico, nach den Regeln der Website und meinen persönlichen Regeln, sollte ich Ihre Antwort ablehnen. Sie sind jedoch neu. Herzlich willkommen! Bitte überprüfen Sie einige der anderen Antworten . Wenn Sie der Meinung sind, dass Ihre Antwort falsch ist, löschen Sie sie anschließend. Bitte geben Sie gerne andere Antworten auf diese und andere Fragen.
Daveloyall
2
Gerade beim Scripting ist manchmal "nichts tun" genau das, was benötigt wird.
Matthew Najmon