rm -rf alle Dateien und alle versteckten Dateien ohne. & .. Error

82

rm -rf /some/path/* löscht alle nicht versteckten Dateien in diesem Verzeichnis (und Unterverzeichnissen).

rm -rf /some/path/.* löscht alle versteckten Dateien in diesem Verzeichnis (aber nicht in Unterverzeichnissen) und gibt außerdem den folgenden Fehler / die folgende Warnung aus:

rm: cannot remove directory: `/some/dir/.'
rm: cannot remove directory: `/some/dir/..'

Was ist der richtige Weg, um alle versteckten und nicht versteckten Dateien und Ordner in einem Zielverzeichnis rekursiv zu entfernen, ohne die Warnung / den Fehler über .und zu erhalten ..?

Jake Wilson
quelle

Antworten:

39

Sie können immer Fehlermeldungen an senden /dev/null

rm -rf /some/path/.* 2> /dev/null

Sie könnten auch nur

rm -rf /some/path/
mkdir /some/path/

... dann müssen Sie sich nicht erst um versteckte Dateien kümmern.

Übelsuppe
quelle
2
Aber was ist, wenn ich nur die versteckten Dateien löschen möchte?
CMCDragonkai
@ CMCDragonkai das sollte eine andere Frage sein, aber du kannst die Lösung in Gilles 'Antwort finden ( rm ..?* .[!.]*sollte es tun).
Evilsoup
15
Wenn Sie das Verzeichnis nicht löschen und neu erstellen, besteht das Risiko, dass die Dateiberechtigungen danach nicht mehr richtig sind (besonders wichtig in Serverumgebungen). Wer könnte den Ordner mit den gleichen Berechtigungen wie bisher automatisch anlegen?
Yo Ludke
1
@YoLudke Sie haben absolut recht, in vielen Situationen spielt es keine Rolle, aber das Löschen des Ordners und das Neuerstellen entspricht semantisch nicht dem Leeren dieses Ordners. Sei also vorsichtig damit!
Thomas
Das Löschen des Verzeichnisses ist nicht immer möglich. In meinem Fall ist das Verzeichnis ein Docker-Volume, und während ich tun kann, was ich will, kann ich das Volume selbst nicht aus dem Container heraus ändern.
Dovidweisz
85

*stimmt mit allen Nicht-Punkt-Dateien .[!.]*überein , stimmt mit allen Punkt-Dateien außer .und mit Dateien, deren Name mit beginnt .., und ..?*stimmt mit allen Punkt-Punkt-Dateien außer überein ... Zusammen stimmen sie mit allen Dateien außer .und überein ... Wenn eines dieser drei Muster mit nichts übereinstimmt, dehnt es sich zu sich selbst aus. rm -fkümmert sich nicht um nicht vorhandene Argumente, das ist also egal.

rm -rf ..?* .[!.]* *

Sie können auch verwenden find. Dies ist komplexer, hat aber den Vorteil, dass es auch dann funktioniert, wenn es so viele Dateien gibt, dass die obigen Platzhalterzeichen über die Befehlszeilenlängenbeschränkung Ihres Systems hinausgehen.

find . -name . -o -prune -exec rm -rf -- {} +

Möglicherweise ist es übersichtlicher, das Verzeichnis zu entfernen und neu zu erstellen. Dies hat den Vorteil (bzw. den Nachteil), dass ein leeres Verzeichnis erstellt wird, selbst wenn ein anderes Programm gleichzeitig Dateien im ursprünglichen Verzeichnis erstellt.

Gilles
quelle
8
Dies sollte die akzeptierte Antwort sein, da dies das Überqueren der Eltern und ein mögliches Löschen verhindert.
Rbellamy
Die findAlternative gibt "Erfolg" zurück, auch wenn eine Datei nicht erfolgreich gelöscht wurde. Nicht gut für Drehbuch.
Franklin Yu
In Bezug auf Ihren zweiten findBefehl heißt es in der Manpage für find: "Da -delete -depth impliziert, können Sie -prune und -delete nicht sinnvoll zusammen verwenden." - doch benutzt du -prune -delete?
Doktor J
@DoktorJ Tatsächlich -prunemacht hier nichts. Und beim Zurücklesen sehe ich, dass ich die Frage nicht richtig beantwortet habe: Ich habe darauf geachtet, nicht zu rekursiv zu werden, aber die Frage fordert ausdrücklich zum rekursiven Löschen auf. Ich habe meine Antwort korrigiert.
Gilles
2
@haylem In zsh müssen Sie .[^.]*anstelle von schreiben, .[!.]*wenn die Verlaufssubstitution aktiviert ist (was standardmäßig interaktiv, aber nicht in Skripten der Fall ist), da zsh !als Verlaufsreferenz analysiert . Aber in zsh würden Sie das überhaupt nicht brauchen, Sie können einfach *(D)Punktedateien (ohne .oder ..) in die Platzhalterübereinstimmung einbeziehen.
Gilles
21

Ich habe gerade festgestellt, dass dies in den meisten Linux-Distributionen der bequemste Weg ist:

ls -A1 | xargs rm -rf

wo

-A= Alles auflisten außer . und..

-1 = setze jeden Gegenstand in eine Zeile

godzillante
quelle
4
Nachteil, den ich sehe, ist: Sie müssen in Verzeichnis 'cd', um dies zu tun.
Kumar
ls -A1 /your/path/ | xargs rm -rfgelten sollte
godzillante
Nein ... es hilft nicht - Zum Beispiel: ls -A1 ~ / test / | xargs rm -rf dieser befehl löscht dateien, in die ich gerade 'cd' bin .. nicht im verzeichnis ~ / test.
Kumar
5
Es funktioniert nicht, wenn einer der Dateinamen Leerzeichen, Zeilenumbrüche, Anführungszeichen oder umgekehrte Schrägstriche enthält.
Stéphane Chazelas
1
-1 Wegen des obigen Kommentars. ↑↑↑↑↑↑↑↑
somethingSomething
15

Ändern Sie entweder die dotglobOption Ihrer Shell und verwenden Sie *oder verwenden Sie etwas wie find.

find somedir -mindepth 1 -delete
Ignacio Vazquez-Abrams
quelle
2
Oder Sie können einfach rm -rf /some/dirund dann ein neues leeres Verzeichnis an seiner Stelle erstellen.
Tripleee
Beste Option bisher. Sehr sicher, da Sie den Verzeichnispfad explizit angeben.
Yanick Girouard
4

Das sollte genauso funktionieren wie @Gilles answer, aber kompakter:

rm -rf {,.[!.],..?}*

oder

rm -rf dir/to/files/{,.[!.],..?}*

sollte auch ein iffür die Verwendung in Skripten hinzufügen, nur um sicher zu sein:

if [ -d "$DIR" ]; then
    rm -rf ${DIR}/{,.[!.],..?}*
fi
Paweł Prażak
quelle
1
Seltsamerweise funktionierte die vorherige Antwort als Bash-Alias ​​unter Ubuntu 16.04 LTS nicht. Tut es alias cleandir='rm -rf {,.[!.],..?}*'jedoch.
Steven Ventimiglia
3

Find ist dein Freund.

find ! -name '.' ! -name '..' -delete

% find ! -name '.' ! -name '..'
./test
./test4
./test4/.test6
./test3
./.test5
./test2
% find ! -name '.' ! -name '..' -delete    
% find ! -name '.' ! -name '..'     
%             

Wenn Sie rekursiv nach etwas anderem in Ihrem aktuellen Verzeichnis suchen möchten ($ PWD), fügen Sie direkt nach dem findBefehl einen Pfad hinzu . zB find /path ! -name '.' ! -name '..' -delete. Wenn Sie nur die nAnzahl der Verzeichnisse verringern möchten , verwenden Sie die -maxdepth nOption direkt nach dem /pathParameter.

Der obige Befehl wurde auf einem Ubuntu 13.04-System getestet. Funktioniert wahrscheinlich auf anderen, modernen Linux-Systemen.

laebshade
quelle
um alle Verzeichnisse im aktuellen Verzeichnis zu löschen, können Sie dies tunfind . ! -name '.' ! -name '..' -type d -delete
Andy
2

Was ist der richtige Weg, um alle versteckten und nicht versteckten Dateien und Ordner in einem Zielverzeichnis rekursiv zu entfernen, ohne die Warnung / den Fehler zu erhalten. und ..?

Angenommen, das fragliche Verzeichnis ist ./dirdann

rm -rf ./dir

würde alle Dateien ./direinschließlich versteckter Dateien und Verzeichnisse rekursiv und einschließlich des ./dirVerzeichnisses selbst entfernen .

Wenn Sie das Verzeichnis selbst nicht löschen möchten, können Sie es anschließend neu erstellen oder verwenden

find ./dir -mindepth 1 -delete

oder wenn Sie findnicht unterstützen -delete,

find ./dir -mindepth 1 -depth -exec rm -rf {} ';'

Mit -mindepth 1können Sie das oberste Verzeichnis behalten ./dir.

Kusalananda
quelle
Dies sollte als beste Antwort markiert werden
kitingChris
1

Ich schlage vor, Sie experimentieren mit

Turn- ON Punkte (versteckte Dateien)

  • einstellen dotglob

    shopt -s dotglob

Turn- OFF Punkte

  • nicht gesetzt dotglob

    shopt -u dotglob

Diese Methode funktionierte genau so, wie ich es mir für einen Kopierbefehl gewünscht hatte, bei dem die versteckten Verzeichnisse fehlten.

    shopt -s    dotglob
    cp    -rvn  ./$from/*  ./$too/
    shopt -u    dotglob

Also habe ich ein Entfernen (Löschen) durchgeführt und hoppla ...

    shopt -s    dotglob
    rm -fr ../message_splitter--044a/*
    shopt -u    dotglob

... das geht auch!

Mir fällt ein, dass Sie, liebe Leserin, das message_splitterVerzeichnis nicht sehen können . Auf jeden Fall hat es einen .svnOrdner, der entfernt und in kopiert werden muss.

Von manSeite ...

dotglob Wenn gesetzt, enthält bash Dateinamen, die mit einem `. 'Beginnen. in den Ergebnissen der Pfadnamenerweiterung.

Verweise:

werden
quelle
-2

Versuchen Sie diesen Code:

Dirlist=``find /some/path/ -type d -name '.[^.]*'`
for HiddenDir in $Dirlist
do
    rm -rf $HiddenDir
done
siz
quelle