Höchstwahrscheinlich, weil das Entfernen des aktuellen Arbeitsverzeichnisses keine gute Idee wäre.
Alexej Magura
Einverstanden - Ich mag das Standardverhalten, aber es ist nicht konsistent mit zB find . -print.
mbroshi
@AlexejMagura Obwohl ich sympathisiere, verstehe ich nicht, warum das Entfernen des aktuellen Verzeichnisses anders sein sollte als das Entfernen einer geöffneten Datei. Das Objekt bleibt am Leben, bis ein Verweis darauf vorhanden ist, und anschließend wird der Müll eingesammelt. Sie können cd ..; rm -r dirmit einer anderen Shell mit ganz klarer Semantik tun ...
Rmano
@Rmano das ist wahr: es ist nur etwas, was ich im Prinzip nicht tun würde: gehe einfach in ein Verzeichnis und lösche dann das aktuelle Verzeichnis. Ich bin mir nicht ganz sicher, warum das so eine große Sache ist - obwohl ich einige Unglücksfälle mit dem aktuellen Verzeichnis hatte, das nicht mehr existiert, wie zum Beispiel, dass relative Pfade nicht mehr funktionieren, aber Sie können immer mit einem absoluten Pfad rauskommen - aber Ein Teil von mir sagt nur, dass es im Allgemeinen keine gute Idee ist.
Alexej Magura
Antworten:
29
Die Mitglieder findutilswissen , dass es mit * BSD kompatibel ist:
Einer der Gründe, warum wir das Löschen von "." dient der Kompatibilität mit * BSD, aus dem diese Aktion stammt.
Der Quellcode von NEWS in findutils zeigt, dass sie beschlossen haben, das Verhalten beizubehalten:
#20802: If -delete fails, find's exit status will now be non-zero. However, find still skips trying to delete ".".
[AKTUALISIEREN]
Da diese Frage zu einem der aktuellsten Themen wird, tauche ich in den FreeBSD-Quellcode ein und finde einen überzeugenderen Grund.
Das Umbenennen von Punkt oder Punkt-zu-Punkt ist verboten, um zyklische Dateisystempfade zu verhindern.
Zyklische Dateisystempfade ?
Ich schaue mir die C Programming Language (2nd Edition) an und suche nach einem Verzeichnis-Thema. Überraschenderweise habe ich festgestellt, dass der Code ähnlich ist :
Jedes Verzeichnis enthält immer Einträge für sich selbst mit der Bezeichnung "." Und das übergeordnete Verzeichnis "..". Diese müssen übersprungen werden, sonst wird das Programm für immer wiederholt .
"loop forever" , das ist dasselbe wie oben renameunter "zyklische Dateisystempfade" beschrieben .
Ich habe den Code leicht modifiziert und ihn unter Kali Linux laufen lassen, basierend auf dieser Antwort :
Wie es sich gehört: POSIX ist König, und das Entfernen des aktuellen Verzeichnisses kann je nach übergeordneter Anwendung und was nicht, einige sehr große Probleme verursachen. Wie wäre es, wenn das aktuelle Verzeichnis wäre /var/logund Sie es als root ausführen würden und denken, es würde alle Unterverzeichnisse und auch das aktuelle Verzeichnis entfernen?
Alexej Magura
1
Das ist eine gute Theorie, aber die manSeite für findsagt: "Wenn das Entfernen fehlgeschlagen ist, wird eine Fehlermeldung ausgegeben." Warum wird kein Fehler gedruckt?
mbroshi
1
@AlexejMagura das aktuelle Verzeichnis Entfernen funktioniert im Allgemeinen: mkdir foo && cd foo && rmdir $(pwd). Es entfernt .(oder ..), was nicht funktioniert.
Die Bedeutung des Löschens von Pfadname / Punkt ist unklar, da der Name der Datei (Verzeichnis) im zu entfernenden übergeordneten Verzeichnis nicht eindeutig ist, insbesondere wenn mehrere Links zu einem Verzeichnis vorhanden sind.
Während 林果 林果 und Thomas bereits gute Antworten dazu gaben, habe ich das Gefühl, dass ihre Antworten vergessen haben, zu erklären, warum dieses Verhalten überhaupt implementiert wurde.
In Ihrem find . -deleteBeispiel klingt das Löschen des aktuellen Verzeichnisses ziemlich logisch und vernünftig. Aber bedenken Sie:
$ find . -name marti\*
./martin
./martin.jpg
[..]
Klingt das Löschen für Sie .immer noch logisch und vernünftig?
Das Löschen eines nicht leeren Verzeichnisses ist ein Fehler - es ist also unwahrscheinlich, dass Sie Daten mit verlieren find(obwohl Sie dies mit könnten rm -r) -, aber das aktuelle Arbeitsverzeichnis Ihrer Shell ist auf ein Verzeichnis festgelegt, das nicht mehr existiert, was zu Verwirrung führt und überraschendes Verhalten:
$ pwd
/home/martin/test
$ rm -r ../test
$ touch foo
touch: cannot touch 'foo': No such file or directory
Das Löschen des aktuellen Verzeichnisses ist einfach ein gutes Schnittstellendesign und entspricht dem Prinzip der geringsten Überraschung.
find . -print
.cd ..; rm -r dir
mit einer anderen Shell mit ganz klarer Semantik tun ...Antworten:
Die Mitglieder
findutils
wissen , dass es mit * BSD kompatibel ist:Der Quellcode von NEWS in findutils zeigt, dass sie beschlossen haben, das Verhalten beizubehalten:
[AKTUALISIEREN]
Da diese Frage zu einem der aktuellsten Themen wird, tauche ich in den FreeBSD-Quellcode ein und finde einen überzeugenderen Grund.
Sehen wir uns den Quellcode des Dienstprogramms find von FreeBSD an :
Wie Sie sehen, wird die
rmdir()
durch POSIX definierte C-Funktion erreicht, wenn Punkt und Punkt nicht herausgefiltert werdenunistd.h
.Führen Sie einen einfachen Test durch. Rmdir mit dem Argument dot / dot-dot gibt -1 zurück:
Schauen wir uns an, wie POSIX rmdir beschreibt :
Es wurde kein Grund angegeben, warum
shall fail
.Ich fand
rename
einige Gründe zu erklären, n:Zyklische Dateisystempfade ?
Ich schaue mir die C Programming Language (2nd Edition) an und suche nach einem Verzeichnis-Thema. Überraschenderweise habe ich festgestellt, dass der Code ähnlich ist :
Und der Kommentar!
"loop forever" , das ist dasselbe wie oben
rename
unter "zyklische Dateisystempfade" beschrieben .Ich habe den Code leicht modifiziert und ihn unter Kali Linux laufen lassen, basierend auf dieser Antwort :
Wir werden sehen:
Es funktioniert korrekt, was nun, wenn ich die
continue
Anweisung auskommentiere:Wie Sie sehen, muss ich Ctrl+ verwenden C, um dieses Endlosschleifenprogramm zu beenden.
Das '..'-Verzeichnis hat seinen ersten Eintrag' .. 'gelesen und wird für immer wiederholt.
Fazit:
GNU
findutils
versucht, mit demfind
Dienstprogramm in * BSD kompatibel zu sein .find
Dienstprogramm in * BSD verwendet intern diermdir
POSIX-kompatible C-Funktion, die Punkt / Punkt-Punkt nicht zulässt.Der Grund
rmdir
dafür, dass Punkt / Punkt-Punkt nicht zugelassen wird, besteht darin, dass zyklische Dateisystempfade verhindert werden.Die von K & R geschriebene Programmiersprache C zeigt beispielhaft, wie Punkt / Punkt-Punkt zu einem Endlosschleifenprogramm führt.
quelle
Weil Ihr
find
Befehl.
als Ergebnis zurückgegeben wird. Von der Infoseite vonrm
:Es sieht also so aus, als würde man sich
find
in diesem Fall nur an POSIX-Regeln halten.quelle
/var/log
und Sie es als root ausführen würden und denken, es würde alle Unterverzeichnisse und auch das aktuelle Verzeichnis entfernen?man
Seite fürfind
sagt: "Wenn das Entfernen fehlgeschlagen ist, wird eine Fehlermeldung ausgegeben." Warum wird kein Fehler gedruckt?mkdir foo && cd foo && rmdir $(pwd)
. Es entfernt.
(oder..
), was nicht funktioniert.Der Systemaufruf rmdir schlägt mit EINVAL fehl, wenn die letzte Komponente ihres Argumentpfads lautet
"."
. Es ist unter http://pubs.opengroup.org/onlinepubs/009695399/functions/rmdir.html dokumentiert. Die Gründe für das Verhalten sind:quelle
Das Aufrufen
rmdir(".")
als Systemaufruf hat nicht funktioniert, als ich es ausprobiert habe, sodass kein übergeordnetes Tool erfolgreich sein kann.Sie müssen das Verzeichnis über den tatsächlichen Namen und nicht über den
.
Alias löschen .quelle
Während 林果 林果 und Thomas bereits gute Antworten dazu gaben, habe ich das Gefühl, dass ihre Antworten vergessen haben, zu erklären, warum dieses Verhalten überhaupt implementiert wurde.
In Ihrem
find . -delete
Beispiel klingt das Löschen des aktuellen Verzeichnisses ziemlich logisch und vernünftig. Aber bedenken Sie:Klingt das Löschen für Sie
.
immer noch logisch und vernünftig?Das Löschen eines nicht leeren Verzeichnisses ist ein Fehler - es ist also unwahrscheinlich, dass Sie Daten mit verlieren
find
(obwohl Sie dies mit könntenrm -r
) -, aber das aktuelle Arbeitsverzeichnis Ihrer Shell ist auf ein Verzeichnis festgelegt, das nicht mehr existiert, was zu Verwirrung führt und überraschendes Verhalten:Das Löschen des aktuellen Verzeichnisses ist einfach ein gutes Schnittstellendesign und entspricht dem Prinzip der geringsten Überraschung.
quelle