Wie leite ich ls an grep weiter und lösche die von grep gefilterten Dateien?

33

Ich wollte ein Paket in meiner Home-Datei löschen, aber der Dateiname war zu lang ( google-chrome-stable_current_i386.deb). Also habe ich beschlossen, den Befehl ls|grep chrome|rmzu verwenden, um die Dateien per Pipe an grep weiterzuleiten, um die Chrome-Datei herauszufiltern und sie dann zu entfernen. Es hat nicht funktioniert, also würde ich gerne sehen, wie ich das machen kann.

SpecialBomb
quelle
22
rm -i *chrome*.deb
Lambert
28
Im Allgemeinen mag ich es nicht, wenn die Leute Antworten auf "Nicht tun" posten, aber dies ist eines der besten Beispiele für ein XY-Problem, das ich je gesehen habe. Ihre eigentliche Frage lautet: "Wie lösche ich schnell eine Datei mit einem langen Dateinamen, ohne das Ganze abzutippen?". Es gibt viele gute Möglichkeiten, die Ausgabe vonls
Michael Mrozek
5
Verwenden Sie einfach find- find . -name "*chrome*" -delete.
Boris die Spinne
3
Meine zwei Cent als StackExchange-Benutzer: Stellen Sie Ihre Frage in Zukunft allgemeiner und geben Sie Details zu den von Ihnen ausgeführten Versuchen an. "Wie lösche ich Dateien in einem Ordner mit einer bestimmten Zeichenfolge im Dateinamen?" könnte ein besserer Weg gewesen sein, es auszudrücken. Dann können Sie einfach hinzufügen, als beiseite, dass Sie Rohrleitungen versucht lsdurch grepzu , rmkonnte aber nicht an die Arbeit. Auf diese Weise erhalten Sie eine oder zwei gute Antworten auf die "richtige" oder "einfachste" Art, Ihre Aufgabe zu erfüllen, anstatt jemanden zu zwingen, Ihnen eine gute Antwort auf eine ineffiziente Lösung zu geben.
Adrian

Antworten:

56

Das ließ mich fast zusammenzucken.

  1. Vielleicht möchten Sie aufhören, die Schrotflinte auf Ihren Fuß zu richten. Grundsätzlich kann jede Art von Parsen von lswird mehr zu kompliziert und fehleranfällig als die etablierten Methoden wie find [...] -execoder Klümpchen .
  2. Sofern nicht jemand eine Troll-Distribution für Sie installiert hat, ist Ihre Shell fertiggestellt Tab. Einfach tippen rm googleund drücken Tab. Wenn der Vorgang nicht sofort abgeschlossen wird, drücken Sie Taberneut, um eine Liste der übereinstimmenden Dateien anzuzeigen. Geben Sie weitere Zeichen des Dateinamens ein, um ihn einzugrenzen, bis er vollständig ist, und führen Sie dann den Befehl aus.
  3. Pipes ! = Parameter . Standardeingabe ist ein binärer Datenstrom , der einem Befehl asynchron zugeführt werden kann. Parameter sind durch Leerzeichen getrennte Zeichenfolgen, die bei der Ausführung nur einmal an einen Befehl übergeben werden. Diese sind sehr selten austauschbar.
l0b0
quelle
1
Tut mir leid, wenn es wie eine n00b-Frage schien. Ich wusste, dass die Verwendung im Allgemeinen in Ordnung war, da das angegebene Paket das einzige Paket war, in dem "Chrom" angegeben ist. Daher würde die Verwendung von grep nur eine Datei herausfiltern. Ich bin ziemlich neu in Linux und habe bereits viele Bash-Skripte erstellt, aber ich weiß noch nicht alles: P. Hart, Alter.
SpecialBomb
5
Wollte nicht hart sein, aber die Hülle ist eine raue und unversöhnliche Umgebung, die sich hinter einer benutzerfreundlichen Oberfläche verbirgt. Es ist schwierig genug, Dinge sicher zu tun , egal ob sicher oder sogar richtig .
l0b0
2
@SpecialBomb Dies ist die einzig richtige Antwort. Es ist sicherlich nicht der richtige Weg, zu erklären, wie man die Schrotflinte richtig zielt, um einen Fuß sauber abzuschneiden, wie es die anderen Antworten tun. Seien Sie besonders vorsichtig, wenn rmSie blind ausführen - dies ist wahrscheinlich die üblichere Methode, um Ihre Distribution zu braten.
Boris die Spinne
@ BoristheSpider Heh, ich habe Ubuntu definitiv schon zweimal gebraten, indem ich AMD-Grafikkartentreiber installiert habe. Ich habe aber schon eine Frage dazu gestellt. AMD war schrecklich, deshalb habe ich gefragt, ob es auf einer AMD-Karte gemeinsame Korrekturen oder bessere Spielmethoden für Linux gibt.
SpecialBomb
34

Sie können den Befehl find auch mit einem Platzhalter verwenden:

find . -maxdepth 1 -name '*chrome*' -delete

Beachten Sie, dass das Argument "-maxdepth" sicherstellt, dass find nur im aktuellen Verzeichnis funktioniert und nicht in Unterverzeichnisse zurückgeführt wird.

Chander
quelle
1
Verbesserungsvorschläge: (a) Verwenden Sie -inamefür Dateinamen ohne Berücksichtigung der Groß- / Kleinschreibung (b) Pipe für die xargsVerwendung von -print0Flag für findund -0Flag für xargs. Die Verwendung von xargsermöglicht es Ihnen, Dinge wie "interaktive" (Löschbestätigung foo?) Zu löschen .
Christopher Schultz
3
Sie müssen keine Pipe an xargs senden, wenn Sie die Option -exec verwenden:find . -name '*chrome*' -exec rm -i {} +
Johnny
4
Wird dies nicht auch rekursiv in Unterverzeichnissen gelöscht? Möglicherweise müssen Sie angeben maxdepth, dass Sie 1 sein
möchten.
32

Sie hatten die richtige Idee, haben nur ein paar Details übersehen. Da Sie mit einer Liste zu tun haben, die zu STDIN kommt und rmParameter erwartet, müssen Sie verwenden xargs.

Somit:

ls | grep chrome | xargs rm

Sollte dir geben, was du willst.

Beachten Sie, dass Sie der Anweisung chromeeinfach hinzufügen können , wenn Sie alles andere als die Datei löschen möchten .-vgrep

Beachten Sie, dass dies nach den anderen Antworten auf diese Frage wahrscheinlich ein schlechter Weg ist, um das zu erreichen, was Sie erreichen möchten.

John
quelle
Mit -v, würde das nicht löscht alles außer für Dateien , die passen chrome? Ich glaube nicht, dass die OP das will ...
akivajgordon
Wenn Sie noch einmal hinsehen, haben Sie recht. Das OP will "die Chromdatei herausfiltern", dann aber entfernen.
John
Dies scheint unnötig komplex, im Vergleich zu einem einfachen „rm -i Chrom
chander
5
Die akzeptierte Antwort funktioniert, aber siehe die Antwort unten, die erklärt, warum es eine schlechte Idee ist. (Diesen Kommentar hier posten, nur für diejenigen, die aufhören, sobald sie ein "akzeptiertes" Häkchen sehen.)
Jim Davis
1
Die akzeptierte Antwort "funktioniert" nur, wenn die lsAusgabe keine "seltsamen" Dateinamen enthält . Dateinamen mit Leerzeichen zerstören dies. Dies ist auch gefährlich, wenn jemand in dem Verzeichnis, in dem Sie dies ausführen, einen Dateinamen mit einer speziellen Sauce erstellen kann. Wie mehr als eine Person bereits darauf hingewiesen hat, analysieren Sie nicht die Ausgabe von ls !
Stephen P
11

Niemals die Ausgabe von ls analysieren
Mein Vorschlag ist, die Ausgabe von ls [ 1 ] nicht zu analysieren , noch mehr, wenn dies in Verbindung mit dem delBefehl geschieht . Dies hängt aus vielen Gründen hauptsächlich mit unerwarteten und nicht üblichen Zeichen zusammen, die im Dateinamen zulässig sind.

Selbst wenn Sie erwarten sollten, dass sich die zu Linux-Paketen gehörenden Dateinamen "gut verhalten" , kann dieses Problem dennoch auftreten, wenn andere Dateien im selben Verzeichnis vorhanden sind, Sie dies jedoch nicht wussten oder bemerkten.

Es ist besser find, die Tabulatorerweiterung (schreiben Sie den Namen und drücken Sie Tab), die Dateinamenerweiterung [ 2 ] als *MyKey*...


Eine schnelle Lösung
Da Sie alle Pakete (die mit enden .deb) mit "google" auswählen möchten, können Sie Ihre Anfrage mit dem Platzhalter erstellen * *google*.debund eine einfache Aktion ausführen

rm -i *google*.deb 

Dadurch wird jeder Dateiname mit "google" in der Mitte ausgewählt, .debder im aktuellen Verzeichnis vorhanden ist. Die Option -i(interaktiv) fordert zur Bestätigung auf, eine gute Gewohnheit, wenn Sie Dateien mit der Parametererweiterung löschen.


Eine Lösung nahe der Philosophie Ihres Versuch
Wenn Ihr Zweck ist der Command Stück für Stück zu bauen, so dass Sie getan haben ls, nach ls | grep google, und erst , nachdem Sie die Ausgabe überprüft Sie es in einer Subshell ausführen kann , $(...)mit

rm -i $(ls | grep google)

Eine schnellere und gefährlichere Methode [ 3 ] ist die Verwendung!!

ls | grep google
rm -i $(!!)

Dadurch wird der letzte in Ihrem Verlauf beendete Befehl ausgeführt . Sie können sich davor schützen, dass Sie keine visuelle Kontrolle über die auszuführende Zeile haben, wenn Sie zuvor die Shell-Optionen histverifymit aktiviert haben shopt -s histverify.

Hastur
quelle
5
touch 0 1 2 3 4 5 6 7 8 9
find . -name \[0-9] -ok rm {} \;

< rm ... ./0 > ? y
< rm ... ./9 > ? y
< rm ... ./8 > ? y
< rm ... ./7 > ? y
< rm ... ./6 > ? y
< rm ... ./5 > ? y
< rm ... ./4 > ? y
< rm ... ./3 > ? y
< rm ... ./2 > ? y
< rm ... ./1 > ? y
^C

... verwenden -name '*c*.deb'Sie stattdessen ein anderes Muster.

mikeserv
quelle
2

rmakzeptiert keine Eingaben von stdin. Sie müssen so etwas tunls google-chrome* | xargs rm

David King
quelle