ubuntuusers.de

Imagemagick bulk resize

Status: Ungelöst | Ubuntu-Version: Lubuntu 14.10 (Utopic Unicorn)
Antworten |

BlackBoxCoder

Anmeldungsdatum:
19. Juni 2013

Beiträge: 22

Hallo Freunde der Nacht,

ich habe mal ein kleines Problem mit einem kleinen Script.

Ich habe ein Script geschrieben, dass mittels imagemagick Bilder aus einem Ordner verkleinert und in einen unterordner verkleinert speichert. Das funktioniert auch soweit ganz gut.

Ich möchte in einer For-Schleife aber alle gängigen Datentypen abfangen, sprich: jpg, jpeg, bmp und png. Dies mache ich mittels for i in *.{jpg,jpeg,png,bmp}

Interessanterweiße versucht nun aber mein Script die convert operation von imagemagick auch auf alle Dateitypen anzuwenden, auch wenn diese nicht im Verzeichnis vorhanden sind.

Hier die Beispielausgabe:

sudo ./thumber.sh /home/blackboxcoder/ 150 150
convert.im6: unable to open image `/home/blackboxcoder//*.jpeg': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: no images defined `/home/blackboxcoder//thumb/*.jpeg' @ error/convert.c/ConvertImageCommand/3044.
convert.im6: unable to open image `/home/blackboxcoder//*.bmp': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: no images defined `/home/blackboxcoder//thumb/*.bmp' @ error/convert.c/ConvertImageCommand/3044.
convert.im6: unable to open image `/home/blackboxcoder//*.png': No such file or directory @ error/blob.c/OpenBlob/2638.
convert.im6: unable to open file `/home/blackboxcoder//*.png' @ error/png.c/ReadPNGImage/3667.
convert.im6: no images defined `/home/blackboxcoder//thumb/*.png' @ error/convert.c/ConvertImageCommand/3044.
converting done!

Hier das entsprechende Script:

1
2
3
4
5
6
7
8
9
#!/bin/bash
if [ $# -gt 2 ]; then  #check if there are more parameter then 2
	mkdir -p $1/thumb #create dir thumb if not exits
	for i in $1/*.{jpg,jpeg,bmp,png}; #for each jpg,jpeg,bmp,png in the dir do
	do
		convert $1/${i##*/} -resize $2x$3 $1/thumb/${i##*/} #convert picture  
	done
	echo "converting done!"
fi

Ich hoffe ihr könnt mein Problem verstehen und habt den ein oder anderen Tipp für mich.

Viel Dank!

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13217

Du brauchst die Bash-Option "nullglob" oder Du musst testen, ob die Datei existiert (Zeilen 10 und 13 einkommentieren). Ich würde auch die Variablen quoten:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#!/bin/bash

shopt -s nullglob

if [ $# -gt 2 ]; then  #check if there are more parameter then 2
        target="$1/thumb"
	mkdir -p "$target" #create dir thumb if not exits

	for i in "$1"/*.{jpg,jpeg,bmp,png}
	do
           # if [ -f "$i" ]; then
                base="${i##*/}"
		convert "$1/$base" -resize "$2x$3" "$target/$base"
           # fi
	done

	echo "converting done!"
fi

Ich habe auch noch die redundanten Kommentare weggelassen.

Ciao

robert

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13217

PS: Noch etwas: ich würde die Fehlerbehandlung anders machen, so dass das Skript oben gleich aussteigt:

1
2
3
4
5
6
7
8
if [ $# -lt 3 ]; then
  echo "ERROR: need three arguments." >&2
  exit 1
fi

target="$1/thumb"
mkdir -p "$target" #create dir thumb if not exits
...

So sparst Du Dir die Einrückung für den Hauptteil und man muss nicht bis unten lesen, um zu sehen, was im Fehlerfall passiert.

BlackBoxCoder

(Themenstarter)

Anmeldungsdatum:
19. Juni 2013

Beiträge: 22

Wow, danke für die direkte Antwort. Ich denke ich werde die Variante nehmen, in der geprüft wird, ob die Datei vorhanden ist.

Das mit dem frühen Abbruch ist ebenfalls sehr gut.

Danke dafür, wird morgen gleich getestet.

Gute Nacht, BBC

Benno-007

Anmeldungsdatum:
28. August 2007

Beiträge: 29240

Wohnort: Germany

Haha, das Problem hatte ich beim selben Zweck auch. 😉 Hab dann auch die Existenz abgeprüft. Die Tests hatten mich eine Menge Zeit gekostet.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13217

BlackBoxCoder schrieb:

Wow, danke für die direkte Antwort. Ich denke ich werde die Variante nehmen, in der geprüft wird, ob die Datei vorhanden ist.

Dann kannst Du das Skript auch mit /bin/sh (das ist die dash) ausführen lassen. Die braucht etwas weniger Resourcen als die bash, obwohl das in diesem Fall vermutlich kaum auffallen wird.

Das mit dem frühen Abbruch ist ebenfalls sehr gut.

Das entspricht auch dem üblichen Muster bei der Programmierung, erst mal die Eingangswerte auf Gültigkeit zu prüfen und im Fehlerfalle abzubrechen. Dann hat man den Code schön sauber getrennt von der eigentlichen Verarbeitung.

Dabei fällt mir auf: In dem Sinne sollte man auch die Existenz des Verzeichnisses in Parameter 1 prüfen, weil sonst ggf. durch den mkdir -p auch dieses Verzeichnis angelegt wird. Das ist aber nicht im Sinne des Erfinders und man braucht dann auch gar nicht anzufangen etwas zu tun, weil dort dann sowieso keine Dateien liegen. Also könnte man noch so etwas in Zeile 5 einfügen:

1
2
3
4
if [ ! -d "$1" ]; then
  echo "ERROR: directory does not exist: $1" >&2
  exit 2
fi

Danke dafür, wird morgen gleich getestet.

Bitte!

Ciao

robert

BlackBoxCoder

(Themenstarter)

Anmeldungsdatum:
19. Juni 2013

Beiträge: 22

Guten Morgen liebe Community,

ich habe die Vorschläge von Robert direkt mal implementiert.

Mit der dash-Variante funktioniert das Script (Zumindest auf meinem Herzkranken-Netbook) um einiges schneller. Die Exceptions habe ich auch eingefügt.

So damit ich es anderen Anwendern leichter machen kann, sollten sie das gleiche oder ein ähnliches Problem haben, füge ich hier auch noch den finalen Code ein.

Robert: ich würde das Script gerne in meinem Blog zur Verfügung, darf/soll ich dich in den Credits im Script erwähnen?

Vielen Vielen Dank für die gesamte Hilfe ☺

Gruß, BBC (Chris)

Nachtrag 08.01.2015 08:54:

bin/sh funktioniert in dem Script nicht. Da wir hier noch den Befehl converting haben. Also wird doch bin/bash benötigt.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
##################Handling exceptions################
if [ $# -lt 3 ]; then
  echo "ERROR: need three arguments." >&2
  exit 1
fi
if [ ! -d "$1" ]; then
  echo "ERROR: directory does not exist: $1" >&2
  exit 2
fi
#####################################################

target="$1/thumb"
mkdir -p "$target" #create dir thumb if not exits
for i in $1/*.{jpg,jpeg,bmp,png}; #for each jpg,jpeg,bmp,png in the dir do
do
if [ -f "$i" ]; then
	base="${i##*/}" #get just the  filename
	convert "$1/$base" -resize "$2x$3" "$target/$base"
fi
done
echo "converting done!"

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13217

BlackBoxCoder schrieb:

Mit der dash-Variante funktioniert das Script (Zumindest auf meinem Herzkranken-Netbook) um einiges schneller.

Wie viel macht das denn aus?

So damit ich es anderen Anwendern leichter machen kann, sollten sie das gleiche oder ein ähnliches Problem haben, füge ich hier auch noch den finalen Code ein.

Fein.

Robert: ich würde das Script gerne in meinem Blog zur Verfügung, darf/soll ich dich in den Credits im Script erwähnen?

Ja, gerne.

Vielen Vielen Dank für die gesamte Hilfe ☺

Gerne.

bin/sh funktioniert in dem Script nicht. Da wir hier noch den Befehl converting haben.

Du brauchst "/bin/sh". In dem Skript gibt es keinen Befehl converting. Was ist der Fehler?

Also wird doch bin/bash benötigt.

Das glaube ich nicht.

BlackBoxCoder

(Themenstarter)

Anmeldungsdatum:
19. Juni 2013

Beiträge: 22

Hey,

eigentlich meinte ich diesen Befehl:

convert "$1/$base" -resize "$2x$3" "$target/$base"

Dieser wird meiner Meinung nach erst gar nicht ausgeführt wenn ich bin/sh statt bin/bash nehme. (ich hatte es ja erst drin, aber nach meinem Nachtrag wieder getauscht 😉 )

Da der Befehl nicht ausgeführt wird, geht es um den Faktor 2-3 schneller (aktuell liegen in dem Ordner 4 Bilder).

Lediglich der Ordner "thumb" wird erstellt.

Gruß, BBC

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13217

BlackBoxCoder schrieb:

convert "$1/$base" -resize "$2x$3" "$target/$base"

Das ist aber ein externer Befehl, wird also nicht von der Shell selbst ausgeführt. Dann kann es nur an irgendwelchen Einstellungen liegen (z.B. $PATH). Oder hast Du vielleicht einen Alias definiert?

Dieser wird meiner Meinung nach erst gar nicht ausgeführt wenn ich bin/sh statt bin/bash nehme. (ich hatte es ja erst drin, aber nach meinem Nachtrag wieder getauscht 😉 )

Dann führ mal das Skript so aus /bin/sh -x script-name verzeichnix x y. Die Debug-Ausgabe gibt dann ggf. einen Hinweis, was da los ist.

Zusätzlich kannst Du mal auf dem Shell-Prompt folgendes eingeben: type -a convert. Dann siehst Du, wie die interaktive Shell das auflöst. Kannst Du natürlich auch oben im Skript einbauen.

Da der Befehl nicht ausgeführt wird, geht es um den Faktor 2-3 schneller (aktuell liegen in dem Ordner 4 Bilder).

Logisch, aber diese Art von Unterschied ist natürlich nicht gemeint.

Lediglich der Ordner "thumb" wird erstellt.

Sehr seltsam.

Antworten |