maxx2019
Goto Top

Shell: Bilder rekursiv verkleinern

Hallo zusammen,

ich lese schon einige Zeit mit und konnte schon viele Tipps und Lösungen finden. Danke dafür.

Ich bin in der Windows-Welt zu Hause und habe mir eine Synology DS218 zugelegt, um meine Daten in meiner eigenen Cloud abzulegen. Das klappt soweit auch ganz gut.

Nun möchte ich, dass in meiner DiskStation für eine schnellere Navigation Bilder automatisch verkleinert werden. Da die Bilder auch vom Handy aus auf die DS geschoben werden und die Rechner mit Windows oft eine ganze Zeit aus bleiben, möchte ich das direkt auf der DiskStation machen.

Die DS kann das leider nicht von Haus aus. Man könnte mit dem Paket PhotoStation arbeiten - da werden beim Upload kleinere Versionen erstellt. Das möchte ich aber nicht, denn das Ding ist recht träge und bietet mir nicht das, was ich gerne hätte. Die PhotoStation ist auch nicht dazu gedacht, alle Bilder zu verwalten, sondern eher eine Galerie für ausgewählte Bilder. Ich hatte nur einen Teil meiner Bilder eingespielt, da wurde die DS merklich langsamer. Also hab ich die PhotoStation wieder entfernt - und siehe da: Die Performance stimmt wieder.

Auf der DS ist die binary convert aus dem ImageMagick verfügbar (mogrify steht nicht zur Verfügung). Einzelne Bilder bekomme ich mit
convert "/volume1/Geteilt/Bilder_Videos/Familie/2019 Maifest/Mein Foto 1.jpg" -resize "1024x1024>" "/volume1/Geteilt/Bilder_Videos/Familie/2019 Maifest/Verkleinert/Mein Foto 1_res_1024.jpg"   
auch verkleinert. Vorausgesetzt ich habe den Unterordner "Verkleinert" vorher angelegt.

Ich möchte gerne, dass das Verzeichnis /volume1/Geteilt/Bilder_Videos/ und alle Unterordner per Cronjob von der DS nach Bildern (JPEGs --> .jpg, .jpeg und alle möglichen abgeleiteten Varianten der Groß-/Kleinschreibung wie .JPEG, .jPG) durchsucht wird und diese dann als verkleinerte Fassung in einem eigenen Unterordner "Verkleinert" im jeweiligen Bilderordner gespeichert werden. Die Namen der Ordner und Bilder enthalten zum Teil Leerzeichen und bisweilen neben Buchstaben, Zahlen, _ und - auch noch weitere Sonderzeichen wie zum Beispiel ä, ö, ü.

Das Ganze soll per Cronjob dann periodisch automatisch angestoßen werden. Dementsprechend sollen Bilder mit bereits erstellten Verkleinerungen übersprungen werden (doppelt erzeugen kostet ja nur unnötig Ressourcen und verlangsamt das Script), ohne dass der Zeitstempel angefasst wird. Das Script sollte nur einmal aktiv sein: Ist ein vorheriger Lauf des Scripts noch nicht abgeschlossen, sollte der neue Scriptaufruf abgebrochen werden, sonst kommen sich die Scriptaufrufe in die Quere.
Kür wäre, wenn in den Unterordnern "Verkleinert" die veralteten verkleinerten Fassungen wieder gelöscht werden, wenn man den originalen Bildnamen geändert oder das Original-Foto vielleicht auch gelöscht hat.

Leider habe ich kaum Erfahrung mit Linux. Ich hab mich schon erforlgreich per SSH auf der DS zugemeldet (WinSCP und Putty).

Was ich schon gemacht habe: Synologyspezifisch und allgemein nach Resize Convert Batch Shell und weiteren unterschiedlichen Kombinationen gegoogelt. Habe auch einiges gefunden, aber irgendwie komm ich damit noch nicht klar. Viele Scripte scheitern insbesondere an der Geschichte mit Leerzeichen und Sonderzeichen im Datei- und Verzeichnisnamen und macht vieles, was ich mit "find" gefunden habe nicht nutzbar oder ich verstehe die Syntax nicht wirklich. Zu Find habe ich einen interessanten Thread gefunden.

Kann mir jemand helfen?

Vielen Dank!

Grüße
Max

Content-Key: 498612

Url: https://administrator.de/contentid/498612

Printed on: April 25, 2024 at 06:04 o'clock

Member: NetzwerkDude
Solution NetzwerkDude Sep 26, 2019 at 14:10:03 (UTC)
Goto Top
Es ist eigentlich nichts synologyspezifisches, mit normalen Bash Befehlen solltest du weiterkommen, z.B.

suchpfad='/volume1/Geteilt/Bilder_Videos/'  

#Mit find alle jpgs finden, damit die schleife füttern, hier alle Verkleinert pfade ignorieren, sonst wirds unendlich rekuvis pro aufruf
find $suchpfad -type f \( -iname "*.jpg" -o -iname "*.jpeg" \) -not -path "*/Verkleinert/*" | while read pic; do  
	#In der Schleife pro Datei prüfen obs schon eine kleine version gibt, sonst eine machen
	dateiname=$(basename "$pic")  
	ordnername=$(dirname "$pic")  
	if [ ! -f "$ordnername/Verkleinert/$dateiname" ]; then  
		mkdir -p "$ordnername/Verkleinert"  
		convert "$pic" -resize "1024x1024>" "$ordnername/Verkleinert/$dateiname"  
	fi;
done;

Den Zusatz das die Verkleinerten gelöscht werden wenn die großen entwernt wurden, kannst ja selber versuchen
Member: Maxx2019
Maxx2019 Sep 26, 2019 at 15:29:14 (UTC)
Goto Top
Danke, NetzwerkDude!

Das sieht verlockend einfach aus. Manchmal kann es so einfach sein. Habs gleich probiert, klappt fast so wie es soll. Lediglich der Dateiname des verkleinerten Bildes passt noch nicht.
Wie schaffe ich es, dass aus der verkleinerten Fassung "Mein Foto 1.jpg" am Ende "Mein Foto 1_res_1024.jpg" wird?

Wie kommt es, dass es keine Probleme mit find gibt? Daran bin ich schon immer gescheitert.

Kann man auch die Anzahl der gefundenen Dateien anzeigen lassen? Einen Counter habe ich mit
num=0
...
((num++))
...
echo "Datei $num"  
hinbekommen.
Member: NetzwerkDude
Solution NetzwerkDude Sep 26, 2019 updated at 17:16:40 (UTC)
Goto Top
Hi,

also die anzahl kannst du mit "wc" messen, also
find <irgendwas> | wc

wegen dem zusatz, eigentlich einfach, aber hier ist noch ein zwischenschritt zu tun:
Da wir die extenstion nicht wissen, kann sie 3-4 stellig sein und groß und kleinschreibung enthalten - daher müssen wir die extension erst finden: (da gibts zig varianten, hier versuchen wir es mit grep und etwas regex)
extension=$(echo $dateiname | grep -Eio '\.[a-z]{3,4}$')  
und dann kann basename die extension abschneiden wenn er Sie kennt (in der klammer) + wir mit etwas concatenation kleben alles andere dran
newname=$(basename "$dateiname" $extension)_res_1024$extension  

d.h. komplett
find $suchpfad -type f \( -iname "*.jpg" -o -iname "*.jpeg" \) -not -path "*/Verkleinert/*" | while read pic; do  
	dateiname=$(basename "$pic")  
	ordnername=$(dirname "$pic")		  
	extension=$(echo $dateiname | grep -Eio '\.[a-z]{3,4}$')  
	newname=$(basename "$dateiname" $extension)_res_1024$extension  

	if [ ! -f "$ordnername/Verkleinert/$newname" ]; then  
		mkdir -p "$ordnername/Verkleinert"  
		convert "$pic" -resize "1024x1024>" "$ordnername/Verkleinert/$newname"  
	fi;
done;