Allgemein
Knowledge Base
- Neue Struktur (In Arbeit)
- Computertechnisches
Community
Privat
/ HomePage / Computer / Software / Programmierung / Massenverarbeitung
Eigentlich sind Scripte für die wiederkehrende Verarbeitung prädestiniert. Wer einmal ein Bild mit Gimp skaliert hat, weiß was das für ein Aufwand ist. Bild öffnen, Bild skalieren, Bild speichern. Das mag sich nicht kompliziert anhören, ist es eigentlich auch nicht, nur, wenn man das dann 10x machen soll wird es schnell langwierig und fehleranfällig, da immer wieder die selben Schritte vorgenommen werden sollen. Ok, für nur 10x kann man es eben noch machen, aber sobald man es irgendwann nochmal machen soll... ist es stupide Arbeit.
Ein Script, oder ein Programm das die Arbeit erledigt. Zum Bearbeiten von Bildern per Script bietet sich ImageMagick an.
convert <Datei> -scale 320x <Neue_Datei>
Es bleibt also nur die Verarbeitung des Dateinamens.
#!/bin/bash # Prüfen, ob ein Parameter übergeben wurde if [ $# -eq 0 ]; then echo "Usage: $0 <Datei>" exit 1 fi if [ ! -e "$1" ]; then echo "Datei existiert nicht" exit 1 fi # Datei zerlegen in dessen eigentlichen Namen und dem Pfad dazu BASENAME=$(basename $1) DIRNAME=$(dirname $1) NEWNAME="img_320x_${BASENAME}" NEWPATH=$DIRNAME/$NEWNAME if [ -e "$NEWPATH" ]; then echo "Neue Datei existiert bereits" exit 1 fi # hier passiert die Umwandlung convert $1 -scale 320x $NEWPATH
Zu speichern als resizeTo320x
Damit können wir jetzt exakt ein Bild in einem beliebigen angegebenen Pfad in 320x wandeln. Die neue Datei fängt immer mit 'img_320x_' an. Es gibt hier zusätzlich ein paar Sicherheitsabfragen, nur um mal zu zeigen wie man das machen könnte.
Wir wollen die resizeTo320x
jetzt aber mehrfach aufrufen.
find . -name '*.jpg' -exec /.../resizeTo320x {} \;
Das tippt man eben so runter.
Nachteile
find . -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.bmp' -o -iname '*.gif' \
-o -iname '*.png' -o -iname '*.tif' -o -iname '*.tiff' -exec /.../resizeTo320x {} \;
Das tippt niemand mehr.
Q: Aber wie die beiden Scripte miteinander verbinden?
A: Pipe!
Also erstellen wir ein Script, was sämtliche Bilder findet.
find . -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.bmp' -o -iname '*.gif' \
-o -iname '*.png' -o -iname '*.tif' -o -iname '*.tiff'
Speichern als listpics
Damit kann man alle Bilder von Typ jpg, jpeg, bmp, gif, png, tif, tiff von der aktuellen Pfad-Position finden, die Namen werden auf der Konsole (Standard out) ausgegeben. Ggf. erweitern.
listpics | resizeTo320x
Das funktioniert so allerdings nicht, da resizeTo320x
nur mit Parametern arbeitet und nicht mit Übergaben aus dem Standard Input.
Man könnte jetzt die resizeTo320x
dahingehend erweitern, das sie beides kann, mit Parametern umgehen und mit Standard Input zurecht kommt, da resizeTo320x aber nur ein Beispiel sein soll, muss eine andere Lösung her.
Warum nicht ein weiteres Script, das uns diese Arbeit abnimmt. Also alle per Standard Input ankommenden Parameter einfach in Parameter umsetzt und unser Script damit aufruft.
#!/bin/bash if [ $# -eq 0 ]; then echo "Caller: which program should be called?" exit 1 fi # echo "external program: $1" CALLER="$1" shift if [ $# -eq 0 ]; then # rufe übergebenes Program mit jeden Parameter der per Standard Input reinkommt read parameter while [ -n "${parameter}" ]; do # echo ${CALLER} $parameter ${CALLER} $parameter shift read parameter done else # übergebe alle Parameter einzeln an das übergebene Program while [ $# -ne 0 ]; do ${CALLER} $1 shift done fi
Speichern als caller
Nun können wir auf der einen Seite Listenausgaben (fast) direkt an andere Scripte übergeben. Ohne uns in jedem Script Gedanken darüber zu machen, wie man es mehrfach anwendet.
listpics | caller resizeTo320x
listpics
findet beliebig viele Bilder und übergibt diese an den caller
der für jeden Standard Input unser Programm resizeTo320x
aufruft. Wir brauchten das resizeTo320x
nicht mehr anpassen, um mit einem Parameter oder mit Standard Input zurechtzukommen. Der Stapelverarbeitung steht nichts mehr im Weg...
Ok ok, gibt es schon. Das hier beschriebene Verfahren ist auch nur mal ein Beispiel, wie man es machen könnte und so etwas gibt es auch schon, wer sich mit Stapelverarbeitung auskennt, weiß dass es dafür xargs gibt.
listpics | xargs -n 1 resizeTo320x
Der xargs Parameter -n 1 besagt, das unser Programm resizeTo320x
für jeden Parameter explizit aufgerufen wird, sonst würden solange Parameter übergeben wie die Shell hergibt (bis zu 32000 Zeichen)
Der caller soll ja auch nur mal aufzeigen, wie xargs intern funktioniert.
Ich konvertiere alle meine Bilder von den propritären Raw Formaten der Kamarahersteller *.cr2, *.nef, etc. immer in das Adobe dng Format. So nutze ich ein einheitliches und offenes Format, um alle Bilder zu archivieren. Dennoch kommt es vor, dass man die Bilder an andere Personen weitergeben möchte. Dafür eignet sich das jpg Format deutlich besser. Um ein ganzes Verzeichnis von dng zu jpg zu konvertieren, habe ich mir folgendes batch geschrieben.
Vorraussetzung sind imagemagick und unf ufraw. Unter Ubuntu zu installieren mit:
sudo apt-get install imagemagick ufraw
#!/bin/bash for f in *.dng do BASENAME=$(basename $f .dng) NEWNAME=$BASENAME.jpg convert -quality 85% $f $NEWNAME done
find . -iname '*schema*' -print0 | xargs -0 -I MYFILE cp MYFILE /tmp/destinationdir
Kopiert mal eben sämtliche Dateien, egal in welchem Unterverzeichnis die '*schema*' im Namen haben nach /tmp/destinationdir. Ist doch eigentlich ganz einfach.