Generieren und verschieben Sie Miniaturansichten rekursiv

7

Ich möchte ein Bash-Skript, das Folgendes ausführt:

  • Suchen Sie Bilder (JPG, JPEG, JPG, JPEG) rekursiv vom aktuellen Verzeichnis abwärts
  • Generieren Sie eine Miniaturansicht mit imagemagicks Konvertierung
  • Verschieben Sie die Miniaturansicht in ein anderes Verzeichnis

Mein aktuelles Skript sieht folgendermaßen aus:

for f in `find . -type f -iname "*.jpg"`
  do
  convert ./"$f" -resize 800x800\> ./"${f%.jpg}_thumb.jpg"
  mv ./"${f%.jpg}_thumb.jpg" /home/user/thumbs/
done

Es werden keine Dateien (oder Ordner mit allen Inhalten) konvertiert, die Leerzeichen / Sonderzeichen enthalten. Ich habe es versucht, print0aber es hat nicht geholfen.

LucaTony
quelle

Antworten:

6

Sie können erweiterte Optionen wie die -setKombination mit prozentualen Escapezeichen verwenden ( %tum den Dateinamen ohne Verzeichnis oder Erweiterung zu extrahieren), um die Größe jeder Datei mit einem einzigen convertAufruf zu ändern, umzubenennen und zu verschieben :

find . -type f -iname \*.jpg -exec convert {} -resize 800x800\> \
-set filename:name '%t' '/home/user/thumbs/%[filename:name]_thumb.jpg' \;
don_crissti
quelle
6

Iterieren Sie nicht über die Ausgabe von find. Das Problem, das Sie haben, ist eine typische Folge davon.

Ihr Beispiel ist aufgrund der Umbenennung der Datei etwas schwierig. Ein nicht sehr effizienter, aber sicherer Weg, dies zu tun, ist die -execOption findund eine zusätzliche shpro Datei, wie folgt :

find . -type f -iname "*.jpg" -exec sh -c 'echo convert "$1" -resize 800x800\> /home/user/thumbs/"${1%.jpg}_thumb.jpg"' -- {} \;

Wenn es Ihnen nichts ausmachen würde, denselben Namen zu verwenden (mit .jpgSuffix anstelle von _thumb.jpg), würde dieses einfache Formular funktionieren und viel effizienter sein:

find . -type f -iname "*.jpg" -exec echo convert "{}" -resize 800x800\> /home/user/thumbs/"{}" \;

Ich habe dort echoAnweisungen hinzugefügt , um die Ausgabe zu überprüfen, bevor die Befehle ausgeführt werden. Entfernen Sie sie, wenn die Ausgabe gut aussieht.

Janos
quelle
2
@janos, phk und don_crissti: Ich habe gerade die Antwort von don akzeptiert, aber ich habe auch die Antworten, die funktionieren, positiv bewertet. Vielen Dank für Ihre Unterstützung Jungs, Sie hatten sehr interessante / lehrreiche Antworten auf meine erste Frage auf dieser Website :)
LucaTony
2

In Ihrer Lösung wurden die Dateinamen auf die Standardeinstellung aufgeteilt, $IFSdie Leerzeichen enthält.

Versuche Folgendes:

while IFS= read -rd '' f; do

    convert ./"$f" -resize 800x800\> ./"${f%.jpg}_thumb.jpg"
    mv ./"${f%.jpg}_thumb.jpg" /home/user/thumbs/

done < <(find . -type f -iname "*.jpg" -print0)

Das finddruckt die durch Nullbytes ( \0) getrennten Dateinamen und setzt mit -d ''Ihnen das Trennzeichen readauf das gleiche.

phk
quelle
@don_crissti Es gibt eine zweite Bedeutung, -formataber ich habe sie falsch verstanden. Es gibt auch, -setaber ich verstehe seine Syntax nicht: imagemagick.org/Usage/files/#save_escapes Ich glaube nicht, dass ich mehr Zeit in diese investieren werde.
Phk
@don_crissti Ich würde alle Dateien als Parameter durchlaufen, find […] -exec mogrify […] {} +aber anscheinend ist es aus einem anderen Grund eine schlechte Idee: "Alle drei Bilder [im Beispiel] werden jedoch in den Speicher eingelesen und dann mit dem einen Befehl geändert. Dies wird nicht empfohlen Lösung für eine Anzahl großer Bilder oder eine sehr große Anzahl von Bildern, da es möglich ist, Speichergrenzen zu erreichen und damit zum Austauschen (Thrashing) von Datenträgern zu gelangen. " (von dem Link in meinem vorherigen Kommentar). Vielleicht ist die Möglichkeit solcher Fälle auch etw. Erwähnenswert in Ihrem langen Übersichtsbeitrag.
Phk
@phk Dein Snipped hat auch funktioniert, aber ich weiß nicht, welche Antwort die bessere / effizientere ist.
LucaTony