Zu Testzwecken habe ich folgende Verzeichnisse erstellt.
user@linux:~$ mkdir dir0{1..3}
user@linux:~$ ls -l
total 12K
drwxr-xr-x 2 user user 4.0K Mei 31 10:45 dir01
drwxr-xr-x 2 user user 4.0K Mei 31 10:45 dir02
drwxr-xr-x 2 user user 4.0K Mei 31 10:45 dir03
user@linux:~$
Dann entfernte ich es mitfind -exec
user@linux:~$ find -type d -exec rmdir {} \;
rmdir: failed to remove '.': Invalid argument
find: ‘./dir02’: No such file or directory
find: ‘./dir01’: No such file or directory
find: ‘./dir03’: No such file or directory
user@linux:~$
Die Verzeichnisse wurden entfernt, ich habe es überprüft.
user@linux:~$ ls -l
total 0
user@linux:~$
Meine Fragen sind:
1) Ich verstehe nicht, warum die Nachrichten da waren. Irgendeine Idee, warum?
rmdir: failed to remove '.': Invalid argument
find: ‘./dir02’: No such file or directory
Ich sehe diese Art von Fehler nicht beirmdir
user@linux:~$ mkdir dir0{1..3}
user@linux:~$
user@linux:~$ ls -l
total 12K
drwxr-xr-x 2 user user 4.0K Mei 31 22:58 dir01
drwxr-xr-x 2 user user 4.0K Mei 31 22:58 dir02
drwxr-xr-x 2 user user 4.0K Mei 31 22:58 dir03
user@linux:~$
user@linux:~$ rmdir *
user@linux:~$
user@linux:~$ ls -l
total 0
user@linux:~$
2) Ist es möglich, diese Nachrichten zu entfernen?
Antwort1
Sie erhalten die Fehlermeldung „Keine solche Datei oder kein solches Verzeichnis“, find
weil find
versucht wird, Verzeichnisse zu öffnen, die gerade entfernt wurden. Standardmäßig werden die Aktionen auf alle übereinstimmenden Elemente im aktuell besuchten Verzeichnis angewendet, bevor mit den Unterverzeichnissen fortgefahren wird.
Fügen Sie -depth
dem Aufruf von hinzu, dass eine Tiefensuche in den Suchpfaden durchgeführt wird. Dies bedeutet wiederum, dass bei der Ausführung find
in einem Verzeichnis dieses bereits besucht wurde und kein erneuter Versuch unternommen wird, es zu besuchen.find
rmdir
Aus diesem Grund ist die -depth
Option bei der Verwendung implizit (in Implementierungen davon hat ).-delete
find
-delete
find . -depth -type d -exec rmdir {} \;
-depth
ist eine Standardoption für das find
Dienstprogramm.
Beachten Sie, dass dies rmdir
nur bei leeren Verzeichnissen funktioniert. Wenn Sie viele nicht leere Verzeichnisse haben, würde der obige Befehl viele Fehlermeldungen erzeugen.
Verwenden Sie stattdessen (sofern Ihr find
System dies unterstützt) Folgendes -empty
:
find . -type d -empty -delete
Dadurch würden leere Verzeichnisse gelöscht.
Mit einem , das weder find
das Nicht-Standard-Noch hat :-delete
-emtpy
find . -depth -type d -exec sh -c '
for dirpath do
set -- "$dirpath"/*
[ ! -e "$1" ] && rmdir "$dirpath"
done' sh {} +
Dadurch wird geprüft, ob die gefundenen Verzeichnisse leer sind. Wenn dies der Fall ist, werden sie gelöscht.
Das ist ein langer Codeabschnitt, um Fehlermeldungen zu vermeiden, die auftreten, wenn Verzeichnisse nicht leer sind. Alle Fehlermeldungen, dieSindDie erzeugten Ergebnisse werden hoffentlich interessanter anzusehen sein, da es sich wahrscheinlich um „Zugriff verweigert“-Fehler handelt. Die Umleitung der Fehler /dev/null
im ersten find
Befehl oben hätte solche Fehler ausgeblendet.
Antwort2
Was vermutlich passiert, ist, dass -exec ... \;
find mit der Konstruktion seine Arbeit Schritt für Schritt erledigt:
- Gehen Sie durch den Verzeichnisbaum und suchen Sie nach Einträgen, die übereinstimmen
-type d
, und rmdir
Führen Sie diese Schritte aus, um die Einträge sofort nach deren Entdeckung auszuführen .
Dies bedeutet, dass in Ihrem Beispiel „find“ nach sucht dir01
, es als Verzeichnis für den späteren Zugriff im Hinterkopf behält, rmdir
es dann ausführt und dann beim Versuch, rekursiv in zu gelangen dir01
, einen Fehler ausführt, weil es nicht mehr existiert.
In diesem Fall sollte die Ausführung mit -exec rmdir {} +
hilfreich sein: Es rmdir dir01 dir02 dir03
wird ein einzelner Aufruf von ausgegeben. Dadurch werden die letzten drei Fehlermeldungen entfernt.
Die Fehlermeldung .
wird angezeigt, weil .
das aktuelle Verzeichnis zwar ein Verzeichnis ist, aber nicht rmdir
gelöscht werden kann, da es nicht leer ist. Verwenden Sie , -min-depth
um die Berücksichtigung zu beenden, indem Sie den Befehl ausführen:
find -mindepth 1 -type d -exec rmdir {} +
Dies ist nicht perfekt; verschachtelte Verzeichnisse oder eine große Anzahl übereinstimmender Verzeichnisse können immer noch dazu führen, dass Fehlermeldungen ausgegeben werden, aber im einfachen Fall aus der Frage sollte dies funktionieren.