Etwas , das ich glaube , ich sollte sicher wissen: Wenn ich ls <something>
, wird rm <something>
entfernen genau die gleichen Dateien , die ls
angezeigt werden ? Gibt es Umstände, unter denen rm
nicht angezeigte Dateien entfernt werden könnten ls
? (Dies ist in der 18.04 Bash)
Edit: danke an alle die geantwortet haben. Ich denke, die vollständige Antwort ist eine Kombination aller Antworten, daher habe ich die am häufigsten gewählte Antwort als "die Antwort" akzeptiert.
Unerwartete Dinge, die ich dabei gelernt habe:
ls
ist nicht so einfach, wie Sie vielleicht denken, wenn Sie mit seinen Argumenten umgehen- In einer einfachen Installation von Ubuntu, .bashrc Aliase
ls
- Benennen Sie Ihre Dateien nicht mit einem Bindestrich, da diese wie Befehlsargumente aussehen können, und die Benennung von one -r verlangt danach!
rm
keine--dry-run
Flagge hat ...find -delete
besser alsrm
? Sie sagen "Deshalb" , aber mir ist völlig unklar, worauf sich das bezieht. Beachten Sie auch, dass Ihrfind
Aufruf alle Dateien im aktuellen Verzeichnis rekursiv löscht , wobeirm
nur die Dateien im unmittelbaren Verzeichnis gelöscht werden. Auch-name *
ist ein No-Op. Alles in allem bin ich ziemlich verwirrt über Ihren Rat ...find
ist, weil Sie es ausführen können, alle Dateien anzeigen und dann den gleichen Befehl mit ausführen können-delete
. Da Sie bereits die Ergebnisse von gesehen habenfind
, sollte es keine Unklarheit darüber geben, was entfernt wird (ich würde gerne mehr Details dazu in Form einer Antwort hören)-delete
anzeigen und dann denselben Befehl mit " ausführen - Aber wie ist das besser als Ausführenls <filespec>
, gefolgt vonrm <filespec>
(dem das OP bereits weiß, wie es geht)?find ... -print
zuerst ausführen , um zu bestätigen, welche Dateien gelöscht werden sollen,find ... -delete
werden die zwischen den beiden Befehlen erstellten Dateien trotzdem gelöscht. Wenn Sie beide-print
und verwenden-delete
, erhalten Sie keine Bestätigung, sondern nur einen nachträglichen Bericht darüber, was gelöscht wurde (und Sie können diesen auch verwendenrm -v
).Antworten:
Nun, beide
ls
undrm
operieren mit den Argumenten, die ihnen übergeben werden.Diese Argumente können eine einfache Datei sein, so
ls file.ext
undrm file.ext
arbeiten auf der gleichen Datei und das Ergebnis ist klar (Liste der Datei / Löschen der Datei).Wenn argument stattdessen ein Verzeichnis ist,
ls directory
listet es den Inhalt des Verzeichnisses auf, währendrm directory
es nicht so funktioniert, wie es ist (dhrm
ohne Flags können Verzeichnisse nicht entfernt werden, wenn Sie dies tunrm -r directory
, werden alle Dateien unterdirectory
und das Verzeichnis selbst rekursiv gelöscht ).Beachten Sie jedoch, dass Befehlszeilenargumente berücksichtigt werden können Shell-Erweiterung , sodass nicht immer gewährleistet ist, dass dieselben Argumente an beide Befehle übergeben werden, wenn sie Platzhalter, Variablen, Ausgaben von anderen Befehlen usw. enthalten.
Als extremes Beispiel denken Sie
ls $(rand).txt
undrm $(rand).txt
, die Argumente sind "gleich", aber die Ergebnisse sind sehr unterschiedlich!quelle
ls
vs,rm *
wo es "versteckte" (Punkt-) Dateien gibt, obwohl dies überhaupt kein fairer Vergleich ist, da ich nicht geschrieben habels *
. Aberrm
ist für sich genommen bedeutungslos, so dass das Ganze wirklich Äpfel und Orangen sind. Wenn ich richtig verstanden habe, ist das der Kern Ihrer Antwort, also gute Arbeit :)ls
vsrm -r
: der Befehlls <directory>
wird im Verzeichnis nicht versteckte Dateien anzeigen, aberrm -r <directory>
wird gelöscht werden, auch die versteckten Dateien.ls
listet sie nicht auf (sofern nicht anders angegebenls -a
) undrm *
löscht sie nicht (sofern Sie dies nichtdotglob
festgelegt haben).Wenn Sie an etwas wie
ls foo*.txt
vs. denkenrm foo*.txt
, werden die gleichen Dateien angezeigt und entfernt. Die Shell erweitert den Glob und übergibt ihn an den betreffenden Befehl. Die Befehle wirken sich auf die aufgelisteten Dateien aus. Eine listet sie auf, eine entfernt sie.Der offensichtliche Unterschied besteht darin, dass, wenn eine dieser Dateien ein Verzeichnis
ls
wäre, der Inhalt aufgelistetrm
würde , dieser jedoch nicht entfernt werden könnte. Das ist in der Regel kein Problem, darm
sich weniger entfernen ließe als von gezeigt wurdels
.Das Hauptproblem ist das Ausführen von
ls *
oderrm *
in einem Verzeichnis, das Dateinamen enthält, die mit einem Bindestrich beginnen . Sie würden auf die Befehlszeilen der beiden Programme erweitert, als ob Sie sie selbst geschrieben hätten, undls
würden-r
"umgekehrte Sortierreihenfolge" bedeuten , während dies eine rekursive Entfernung bedeutenrm
würde-r
. Der Unterschied ist wichtig, wenn Sie Unterverzeichnisse haben, die mindestens zwei Ebenen tief sind. (ls *
Zeigt den Inhalt der Verzeichnisse der ersten Ebene an, aberrm -r *
auch alles , was über die erste Unterebene hinausgeht.)Um dies zu vermeiden, schreiben Sie zulässige Globs mit einem Anführungszeichen
./
, um das aktuelle Verzeichnis anzuzeigen, und / oder setzen Sie ein--
, um das Ende der Optionsverarbeitung vor dem Glob (dhrm ./*
oderrm -- *
) anzuzeigen .Bei einem Glob wie
*.txt
ist das eigentlich kein Problem, da der Punkt ein ungültiges Optionszeichen ist und einen Fehler verursacht (bis jemand die Hilfsprogramme erweitert, um eine Bedeutung dafür zu finden), aber es ist immer noch sicherer, das zu setzen./
dort zu platzieren.Natürlich könnten Sie auch unterschiedliche Ergebnisse für die beiden Befehle erhalten, wenn Sie die Globbing-Optionen der Shell ändern oder Dateien zwischen den Befehlen erstellen / verschieben / entfernen, aber ich bezweifle, dass Sie einen dieser Fälle gemeint haben. (Der Umgang mit neuen / verschobenen Dateien wäre extrem umständlich und sicher.)
quelle
Konzentrieren wir uns, abgesehen vom Shell-Verhalten, nur auf das, was
rm
undls
können mit sich selbst umgehen. Mindestens ein Fall, in dem angezeigtls
wird, wasrm
nicht entfernt werden kann, betrifft Verzeichnisberechtigungen und der andere - spezielle Verzeichnisse.
und..
.Ordnerberechtigungen
rm
Dies ist eine Operation in einem Verzeichnis, da Sie durch das Entfernen einer Datei den Verzeichnisinhalt ändern (oder mit anderen Worten die Liste der Verzeichniseinträge, da das Verzeichnis nur eine Liste von Dateinamen und Inodes ist ). Dies bedeutet, dass Sie Schreibrechte für ein Verzeichnis benötigen. Auch wenn Sie der Eigentümer der Datei sind , können Sie ohne Verzeichnisberechtigungen keine Dateien entfernen. Das Gegenteil ist auch der Fall : Sierm
können Dateien entfernen, die anderen gehören, wenn Sie Verzeichnisbesitzer sind.So können Sie sehr gut gelesen haben und Ausführungsberechtigungen für ein Verzeichnis, das Sie das Verzeichnis und Sichten des Inhalts innerhalb von nur gut, zum Beispiel durchqueren können
ls /bin/echo
, aber Sie können nicht ,rm /bin/echo
es sei denn Sie sind der Besitzer/bin
oder Ihre Privilegien erhebensudo
.Und Sie werden solche Fälle überall sehen. Hier ist ein solcher Fall: https://superuser.com/a/331124/418028
Spezielle Verzeichnisse '.' und '..'
Ein weiterer Sonderfall ist
.
und..
Verzeichnisse. Wenn duls .
oder tustls ..
, zeigt es dir gerne den Inhalt an, aberrm
es ist nicht erlaubt:quelle
Wenn Sie
ls *
und dann tippenrm *
, werden möglicherweise mehr Dateien alsls
angezeigt entfernt - sie wurden möglicherweise in dem winzigen Zeitintervall zwischen Endels
und Anfang von erstelltrm
.quelle
/tmp
, wenn viele Anwendungen temporäre Dateien erstellen können, sodass dies in beiden Befehlen immer möglich ist*
. Einige Anwendungen machen Dateien jedoch auch anonym, indemunlink()
sie das Datei-Handle geöffnet lassen, sodass sie zwar angezeigt,ls *
aberrm *
möglicherweise nicht abgefangen werden.*
es einen Unterschied zwischen dem gibt, wasls
angezeigt wird und dem, was ausgeführt wirdrm
, da sich die Auflistung der Verzeichnisinhalte zwischenzeitlich geändert hat.ls *
Dateiname angezeigt werden kann, der bereits weg ist.ls *
undrm *
sind nicht dafür verantwortlich, den Glob zu erweitern - das erledigt die Shell, bevor sie ihn an den Befehl übergibt.Das bedeutet, dass Sie mit der erweiterten Dateiliste jeden Befehl verwenden können - ich würde also etwas verwenden, das so wenig wie möglich funktioniert.
Ein besserer Weg, dies zu tun (oder zumindest einen anderen Weg), besteht darin, den Mittelsmann zu überspringen.
echo *
zeigt Ihnen genau, was an Ihrenrm
Befehl weitergegeben werden würde.quelle
printf "%s\n" *
um einen eindeutigen Überblick über Dateinamen mit Leerzeichen zu erhalten. (Oder%q
stattdessen, um auch mit Zeilenumbrüchen und Steuerzeichen umzugehen, auf Kosten einer hässlicheren Ausgabe.)Wie wäre es mit:
Grundsätzlich können Platzhalterzeichen, die auf Dinge erweitert werden, die mit beginnen
-
(oder manuell eingegebene Dinge, die mit beginnen,-
aber ein bisschen mehr nach Schummeln aussehen), vonls
und unterschiedlich interpretiert werdenrm
.quelle
Es gibt Randfälle, in denen das, was
ls
zeigt, nicht das ist, wasrm
entfernt wird. Ein ziemlich extremes, aber glücklicherweisels
harmloses Argument ist, wenn das von Ihnen übergebene Argument ein symbolischer Link zu einem Verzeichnis ist: Zeigt alle Dateien im verknüpften Verzeichnis an,rm
entfernt den Symlink und lässt das ursprüngliche Verzeichnis und seinen Inhalt unverändert:quelle
ln -s $HOME some_link; ls some_link
Ausgängesome_link@
für mich, aber ich habe zuls
befangenls -F
. Anscheinend wird-F
das Verhalten dahingehend geändert, dass der Link angezeigt wird, anstatt ihn zu dereferenzieren. Das habe ich nicht erwartet.ls -l
wenn beispielsweise der Link als Ziel und nicht das Ziel ausgewählt wird, muss es Möglichkeiten geben, den Link selbst zu überprüfen.ls
undrm
.ls some_link/
, wird das verknüpfte Verzeichnis aufgeführt, auch wenn Sie oder hinzufügen . Umgekehrt (sozusagen) sagt man, man solle sich ein Verzeichnis und nicht dessen Inhalt ansehen. vergleichen und .ls -H some_link
ls -L some_link
-F
-l
-d
ls -l /tmp
ls -ld /tmp
ls
. Sie zeigen im Grunde, warum es sich nicht lohnt, Verhaltensweisen mit verschiedenen Flaggen aufzuzählen, um diese Frage zu beantworten ...Wenn Sie dies nur
ls
anstelle von tunls -a
,rm
kann yes versteckte Dateien entfernen, die Siels
ohne nicht gesehen haben-a
.Beispiel
Gemäß :
ls dir_test
: zeigt nur test2 anls -A dir_test
: zeigt test2 + .test anrm -r dir_test
: entfernt alles (.test + test2)Ich hoffe das wird dir helfen.
quelle
rm *
werden keine Punktedateien entfernt. Wenn ja,ls *
werden sie auch angezeigt.ls *
keine versteckten Dateien anzeigen.ls -a
listet.
,..
,.test
undtest2
. Möglicherweise möchten Sie Ihr Beispiel ändern, umls -A
alles außer.
und..
(dh nur.test
undtest2
) aufzulisten.Es gibt bereits viele gute Antworten, aber ich möchte einen tieferen Einblick hinzufügen.
Stellen Sie sich die Frage: An wie viele Parameter werden beim
ls
Schreiben übergeben?...? Beachten Sie, dass der
ls
Befehl den*
as-Parameter nicht erhält , wenn Dateien vorhanden sind,*
auf die erweitert werden kann. Stattdessen führt die Shell zuerst ein Globbing durch, bevor sie den Befehl aufruftls
Befehl tatsächlich so viele Parameter erhält, wie Dateien vorhanden sind, die mit dem Globbing übereinstimmen. Um das Globen zu unterdrücken, geben Sie den Parameter an.Dies gilt für jeden Befehl ein :
echo *
vsecho '*'
.Es gibt ein Skript, rufen Sie es
countparams.sh
auf, um den Effekt zu testen. Es gibt an, wie viele Parameter übergeben wurden, und listet sie auf.Machen Sie es ausführbar und führen Sie es aus
./countparams.sh *
. Lernen Sie aus seiner Leistung!quelle
Der Glob wird beide Male auf dieselbe Weise erweitert, wenn der Verzeichnisinhalt zu diesen beiden unterschiedlichen Zeiten identisch ist.
Wenn Sie wirklich überprüfen möchten, was entfernt wird, verwenden Sie
rm -i *.txt
. Sie werden für jede Datei einzeln aufgefordert, bevor Sie versuchen, sie zu entfernen.Dies ist gegen die Rennbedingungen garantiert sicher:
ls *.txt
/ Es wird eine neue Datei erstellt /rm *.txt
Sie werden von demselben Programm, das die Entfernung durchführt, zu jeder Datei aufgefordert.
Dies ist zu umständlich für den normalen Gebrauch, und wenn Sie Alias
rm
zurm -i
, Sie finden sich mit\rm
oderrm -f
ziemlich oft. Zumindest ist zu erwähnen, dass es eine Lösung für die Rennbedingungen gibt. (Es ist sogar auf Nicht-GNU-Systeme übertragbar: POSIXrm(1)
gibt die-i
Option an .)Eine andere Option wäre ein Bash-Array.
to_remove=(*.txt)
Bitten Sie dann den Benutzer, dies zu bestätigen (möglicherweise nachdem Sie dies getan habenls -ld -- "${to_remove[@]}"
)rm -- "${to_remove[@]}"
. Die Glob-Erweiterung wird also nur einmal ausgeführt und die Liste wird wörtlich an übergebenrm
.Eine weitere praktisch verwendbare Option ist GNU
rm -I
( Manpage ), die zum Entfernen von mehr als 4 Elementen auffordert. (Zeigt Ihnen jedoch nicht die Liste, sondern nur die Gesamtsumme an.) Ich verwende siealias rm='rm -I'
auf meinem Desktop.Es ist ein guter Schutz vor fettem Fingersatz mit einem zu viel passenden, halb getippten Muster. Die Verwendung von
ls
first ist jedoch in der Regel in einem eigenen Verzeichnis oder auf einem Einzelbenutzersystem sinnvoll, und wenn es keine Hintergrundprozesse gibt, die dort asynchron neue Dateien erstellen könnten. Geben Sie nichtrm -rf /foo/bar/baz
von links nach rechts ein , um Fett zu vermeiden .rm -rf /
ist speziell verkleidet, aberrm -rf /usr
nicht! Lassen Sie das-rf
Teil weg oder beginnen Sie mitls
und fügen Sie dasrm -rf
Teil erst hinzu, nachdem Sie den Pfad eingegeben haben.quelle