Bash-Kopie aller Dateien, die nicht mit den angegebenen Erweiterungen übereinstimmen


7

Wenn ich in Shotwell Bilder von meiner Kamera importiere, werden auch die Videoclips importiert. Das ist etwas nervig, da ich meine Videos in einem anderen Ordner speichern möchte. Ich habe versucht, einen Bash-Befehl zu schreiben, habe aber keinen Erfolg gehabt.

Ich benötige einen Befehl, der die folgenden Anforderungen erfüllt:

  • Suchen Sie alle Dateien in einer Verzeichnisstruktur, die nicht die Erweiterung .jpg, .png, .gif oder .xcf haben (ohne Berücksichtigung der Groß- und Kleinschreibung).
  • Verschieben Sie alle diese Dateien in ein Zielverzeichnis, unabhängig davon, ob die Dateinamen oder Verzeichnispfade Leerzeichen oder Sonderzeichen enthalten.

Jede Hilfe wäre dankbar!

BEARBEITEN: Ich verwende die Standard-Shell in Ubuntu, was bedeutet, dass einige Befehle Aliasing usw. sind.

EDIT 2: Ich habe es selbst versucht (nicht der Kopierteil, nur die Auflistung der Dateien). Ich habe extglob aktiviert und den folgenden Befehl ausgeführt:

$ ls -R /path | awk '
  /:$/&&f{s=$0;f=0}
  /:$/&&!f{sub(/:$/,"");s=$0;f=1;next}
  NF&&f{ print s"/"$0 }'

Dies listet alles auf. Ich habe versucht, grep am Ende zu verwenden, habe aber nicht die geringste Ahnung, wie ich es dazu bringen kann, dass es nicht mit einem Muster übereinstimmt, das ich ihm gebe. Der extglob-Schalter hat bei grep nicht viel geholfen, obwohl er bei anderen Befehlen hilft.


Sie haben besseres Glück, dies selbst zu versuchen und bestimmte Fragen zu stellen, was falsch läuft.
drs

Antworten:


12

Sie können verwenden find, um alle Dateien in einem Verzeichnisbaum zu finden, die mit bestimmten Tests übereinstimmen (oder nicht übereinstimmen), und dann etwas damit zu tun. Für dieses spezielle Problem können Sie Folgendes verwenden:

find -type f ! \( -iname '*.png' -o -iname '*.gif' -o -iname '*.jpg' -o -iname '*.xcf' \) -exec echo mv {} /new/path \;

Dies beschränkt die Suche auf reguläre Dateien ( -type f) und dann auf Dateien, deren Namen in keinem Fall ( ) oder ( ) !die Erweiterung haben ( ) usw.). Alle Erweiterungen sind in einer einzigen Bedingung zwischen gruppiert . Für jede übereinstimmende Datei wird ein Befehl ( ) ausgeführt, der die Datei, deren Name anstelle von eingefügt wird , in das Verzeichnis verschiebt . Das sagt, dass der Befehl beendet ist.*.png-iname '*.png'-o*.gif\( ... \)-exec{}/new/path\;find

Die Namensersetzung erfolgt innerhalb des Programmausführungscodes, sodass Leerzeichen und andere Sonderzeichen keine Rolle spielen.


Wenn Sie dies nur in Bash tun möchten, können Sie die erweiterten Mustervergleichsfunktionen von Bash verwenden . Diese erfordern, dass eingeschaltet shopt extglobist, und globstarauch. Verwenden Sie in diesem Fall:

mv **/!(*.[gG][iI][fF]|*.[pP][nN][gG]|*.[xX][cC][fF]|*.[jJ][pP][gG]) /new/path

Dies stimmt mit allen Dateien in Unterverzeichnissen ( **) überein *.gif, die *.pngin keiner Kombination von Zeichenfällen usw. übereinstimmen , und verschiebt sie in den neuen Pfad. Die Erweiterung wird von der Shell durchgeführt, sodass Leerzeichen und Sonderzeichen keine Rolle mehr spielen.

Oben wird davon ausgegangen, dass sich alle Dateien in Unterverzeichnissen befinden. Wenn nicht, können Sie den Teil danach wiederholen **/, um auch das aktuelle Verzeichnis einzuschließen.

Es gibt ähnliche Funktionen in zshund anderen Shells, aber Sie haben angegeben, dass Sie Bash verwenden.


(Ein weiterer Hinweis: Parsen lsist niemals eine gute Idee - probieren Sie es einfach nicht aus.)


1
Dies nur für GNU-Suche, nicht für POSIX-Suche.
Cuonglm

Ich denke, du wärst besser dran -exec mv {} +. Auch - du liegst falsch ls. Es macht das Gegenteil find. find findet ls Listen. Es analysiert sich übrigens von selbst. Und selbst wenn das, was ich sage, nicht wahr ist, machen Sie sicher keinen Versuch, Ihre pauschale Aussage zu sichern. Und bitte verlinken Sie nicht auf dieses Wooledge-Wiki-Ding - es ist eine schreckliche Informationsquelle - und nicht nur auf dieser Seite. Hier ist meinerseits ein gutes Beispiel dafür, wie einfach es lsist, analysiert zu werden. Übrigens - es würde dort genauso funktionieren, wenn es sich um Zeilenumbrüche und nicht um Leerzeichen handelt
mikeserv

Hast du das auf die falsche Antwort geschrieben?
Michael Homer

Es könnte gebrauchen +, aber es spielt wirklich keine Rolle und es ist viel weniger klar. Ich dachte, es könnte die falsche Antwort sein, da ich hier nicht auf Wooledge verlinkt habe (obwohl ich in anderen Antworten zweifellos gelesen habe), so dass "diese Seite" wie eine baumelnde Referenz erscheint.
Michael Homer

3
Neulich ging es darum, variable Erweiterungen zu zitieren (sie sind übrigens dafür); Ich stimme zu, dass es oft ein bisschen begeistert ist. Ich stimme auch zu, dass die verknüpfte Antwort lsübrigens zeigt, wie einfach es ist, analysiert zu werden, aber ich denke, wir unterscheiden uns darin, wie einfach das ist - das war eine Menge kluger Arbeit. "Niemals tun" ist also immer noch ein guter allgemeiner Rat an alle, die Rat brauchen
Michael Homer

2

Sie verwenden Ubuntu, damit Sie GNU finden können. Versuchen Sie:

find . -maxdepth 1 ! -iregex ".*\.\(jpg\|png\|gif\|xcf\)$" -exec mv -- -t /path/to/newdir "{}" +
  • -iregexVerwenden Sie Regex, um den Dateinamen zu finden. Wenn Sie jedoch die Groß- und Kleinschreibung nicht !berücksichtigen, wird der Regex negiert.

  • -exec command +Befehl für übereinstimmende Dateien ausführen. Es ist wie find -print0mit xargs -0. Auf diese Weise können wir mehrere mit einem mvBefehl gefundene Dateien verschieben , sodass die Gesamtzahl der Aufrufbefehle geringer ist als die Anzahl der übereinstimmenden Dateien.

  • -maxdepth 1Beschränken Sie finddie Suche nur im aktuellen Verzeichnis. Wenn Sie rekursiv arbeiten möchten, entfernen Sie es.


0

Es besteht keine Notwendigkeit, dies zu komplizieren! Warum nicht einfach:

mkdir ../temp
mv  *.{jpg,png,gif,xcf} ../temp/
mv * /desired/target/directory/
mv ../temp/* .
rmdir ../temp

Dies funktioniert natürlich nicht für einen ganzen Verzeichnisbaum, sondern nur für ein flaches Verzeichnis von Dateien.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.