Bash: Befehl für Ergebnisse von FIND ausführen

7

Ich versuche, die Größe aller Dateien zu ändern, die mit einem FIND-Befehl gefunden wurden (dies sind alle Dateien in einem Verzeichnis und seinen Unterverzeichnissen). Ich habe viele Optionen ausprobiert, bin aber jedes Mal auf verschiedene Fehler gestoßen. Dies ist mein letzter Versuch:

find /my/folder/ -name '*jpg' -exec 'mogrify -resize 900">"{}' \;

Ich habe viele andere ausprobiert, aber ohne Erfolg. Was geht schief


quelle
Was genau ist der Befehl, den Sie ausführen möchten? mogrify -resize 900">" foo.jpg?
DerfK

Antworten:

11

Ich mag Exec on Find nicht sehr, es ist ein bisschen alt und unvorhersehbar, besonders wenn man alle Zitate füttert :)

Versuchen Sie es mit xargs, es sollte sich etwas zivilisierter verhalten

find /my/folder/ -name '*jpg' -print0 | xargs -0 -J% "mogrify -resize 900 > %"

Dinge, die hier anders sind

-print0 on find fügt nach jedem Dateinamen ein NULL-Zeichen als Trennzeichen hinzu

in xargs

-0 gibt an, dass die Eingabe durch NULL getrennt ist. Char -J% gibt an, dass% durch den Inhalt der Eingabe ersetzt werden soll (in diesem Fall Dateiname).

Luchsmann
quelle
Ha diesmal hast du mich geschlagen @lynxman! Ich muss ernsthaft einen Blog-Beitrag schreiben "-exec als schädlich". Oh, und ich werde Ihnen in ein paar Stunden nach Ablauf meines Tageslimits eine positive Bewertung geben.
Phil Hollenback
Vielen Dank! Aber ich bekomme: xargs: ungültige Option - 'J' Auch mogrify -resize 900 ">" foo.jpg ändert die Größe nur, wenn sie breiter als 900 Pixel ist (daher das ">" zwischen Anführungszeichen.
1
Auf meinen Xargs hier möchten Siexargs -0 -I% mogrify -resize 900">" %
DerfK
Bonus: Wenn Sie -Px hinzufügen (wobei x eine Ganzzahl ist), werden so viele Prozesse verwendet, um den Befehl auszuführen (damit Sie mehrere Kerne nutzen können)
mikelikespie
1
mikelikespie sehe meine Antwort für einen alternativen Weg, um das Gleiche ein bisschen beeindruckender über die Waffe parallel zu machen.
Phil Hollenback
7

@lynxman hat den traditionellen Rat von find / xargs übernommen. Eine andere Alternative ist jedoch die Verwendung von find mit gnu parallel . Parallel bietet einige nette Verbesserungen für xargs, wie eine ausgefeiltere Argumentbehandlung und die Möglichkeit, viele Jobs parallel auszuführen (mir ist klar, dass einige neuere Versionen von xargs auch parallele Jobs unterstützen).

Mal sehen, ob wir dies parallel umschreiben können. Wie wäre es mit:

find /my/folder -name '*jpg' -print0 | parallel --progress -0 -j +0 "mogrify -resize 900\> {}"

Dadurch werden alle JPEG-Dateien gefunden und parallel ausgeführt. parallel führt so viele Jobs parallel aus, wie Sie über CPU-Kerne verfügen ( -j +0).

Wenn Sie viele Dateien verarbeiten, können Sie durch intelligentes Stapeln der Jobs auf diese Weise erhebliche Zeiteinsparungen erzielen. Die --progressOption zeigt einige Details an, während der Job ausgeführt wird.

Der -print0Befehl from the find verwendet Nullen, um die Ausgabe zu trennen, falls Ihre Dateinamen Leerzeichen oder seltsame Zeichen enthalten. Die -0Option zum parallelen Erwarten erwartet eine durch Nullen getrennte Eingabe. Wenn Sie sicher sind, dass Ihre Eingabedateinamen keine Leerzeichen enthalten, können Sie diese weglassen -print0 / -0. Beachten Sie, dass die meisten Versionen von xargs auch die -0Option verwenden, sodass Sie diesen Trick sowohl mit xargs als auch mit parallel verwenden können.

EDIT: Aus Kommentaren habe ich die Befehle nicht ganz richtig verstanden. Mogrify wurde jetzt angepasst, da ich tatsächlich versucht habe, es zu verwenden. Sie müssen nicht in neuen Dateien speichern, da mogrify standardmäßig in die vorhandene Datei schreibt.

Phil Hollenback
quelle
Erstaunliche Arbeit Phil! \ o /
Lynxman
1
Danke für die Ausbildung hier! Ich habe versucht, es zu schaffen, konnte und konnte es aber nicht. Das Flag -0 ist ein Tipp, den ich im parallelen Befehl denke, aber auch ohne das druckt es nur die Befehle ohne Ergebnisse. Übrigens: Mit mogrify -resize ">" 200 können Sie die Größe eines Bildes NUR auf 200 ändern, wenn es größer als 200 ist (also nur abnehmen, nicht erhöhen). Sehr hilfreich.
huh lass mich es noch einmal versuchen und reparieren. -0 ist definitiv eine gültige Option für Parallel. Könnten Sie vielleicht eine alte Version haben? Nicht sicher.
Phil Hollenback
Kleine Optimierungen: -0 / -print0 wird nur benötigt, wenn der Dateiname \ n enthält (Leerzeichen oder 'oder "sind kein Problem). -J +0 ist seit 20110122 Standard. {} Wird hinzugefügt, wenn {} nicht in der Liste enthalten ist Befehl. Es müssen nur Sonderzeichen in Anführungszeichen gesetzt werden. Dies sollte also äquivalent sein: find / my / folder -name '* jpg' | parallel --progress mogrify -resize 800 "\>" Siehe GNU Parallel, wenn Sie sich bei FOSDEM fosdem befinden. org / 2011 / Zeitplan / Veranstaltung / Parallel
Ole Tange
1
Danke Ole für die Tipps. Ich lerne offensichtlich immer noch parallel.
Phil Hollenback
2

Bearbeiten: Entschuldigung, ich habe gerade festgestellt, dass dies keine Umleitung in Ihrem Befehl ist. Es ist eine besondere Anweisung an mogrify.

Ich würde die einfachen Anführungszeichen weglassen und Folgendes versuchen:

find /my/folder/ -name '*jpg' -exec mogrify -resize 900">" {} \;

Wenn Sie den Befehl so verwenden, wie Sie ihn veröffentlicht haben, erhalten Sie wahrscheinlich folgende Fehlermeldungen:

find: `mogrify -resize 900">"filename': No such file or directory.

Ursprüngliche Antwort:

Damit die Umleitung in -execIhnen funktioniert , müssen Sie Folgendes verwenden sh -c:

find /my/folder/ -name '*jpg' -exec sh -c 'mogrify -resize 900 > "$@" ' _ {} \;

Erst in den letzten Tagen habe ich angefangen, Leute zu sehen, die die Verwendung in Frage stellen -exec. Ich habe niemanden speziell sagen sehen, was daran falsch ist. Ich habe viel Erfahrung damit und es hat mich nie enttäuscht. Es gibt jedoch Zeiten, die xargsaufgrund der Kontrolle und der Fähigkeit, mehrere Argumente gleichzeitig zu übergeben , definitiv vorteilhaft sind. Wenn Sie jedoch verwenden -I, wird jeweils nur ein Argument übergeben. Der hier gezeigte Befehl hat den Nachteil, dass die Shell für jede gefundene Datei aufgerufen wird.

Bis auf weiteres angehalten.
quelle
0

Es ist alt hier, aber niemand sagte etwas über ein einfaches:

ls | xargs mogrify -resize 900

-goodFügen Sie auch alle Dateien im aktuellen Verzeichnis für eine benutzerdefinierte Thunar-Aktion hinzu -quality xx.

Oder für benutzerdefinierte Aktionen nur für ausgewählte Dateien:

mogrify-Größe 900% F.

dav
quelle
1
Verwenden Sie nicht ls. Es ist nicht dafür ausgelegt. Verwenden Sie einen Glob.
Tom O'Connor
Es tut uns leid? Bisher habe ich es benutzt und es funktioniert ziemlich gut!
Dav
ok, ich folge, aber wenn das Verzeichnis die Erweiterungen .jpg und .jpeg hat, werden die .jpeg-Dateien dann übersehen, wenn der Glob * .jpg ist?
Dav
erweitertes globbing und benutze *. (jpg | jpeg) oder ähnliches - linuxjournal.com/content/bash-extended-globbing
Tom O'Connor
Es ist nicht ungewöhnlich, dass JPEG-Dateien Leerzeichen in ihren Namen haben. Dieser Befehl funktioniert in diesem Fall nicht.
Bis auf weiteres angehalten.