Wenn man viel mit bash-Skripten macht, kommt man oft an das Problem, dass man Multicore-Prozessoren nicht richtig ausreizen kann. Nehmen wir das Beispiel, dass man alle *.tif Bilder in einem Ordner mit Hilfe von imagemagick zu TIFF/JPEG komprimieren moechte. Das Skript:
for i in *.tif ; do convert $i -compress JPEG $i; done |
for i in *.tif ; do convert $i -compress JPEG $i; done
macht dieses, ein Bild nacheinander. Man koennte das ganze nun schneller machen, indem man einfach jeden convert in eine Subshell packt:
for i in *.tif ; do convert $i -compress JPEG $i &; done |
for i in *.tif ; do convert $i -compress JPEG $i &; done
kommt dann aber sehr schnell in Schwierigkeiten, wenn dann nen Ordner mit z.B. 500 Bildern hat und dann auch 500 Subshells. Eine elegantere Loesung ist, eine maximale Anzahl von Prozessen anzugeben die nicht ueberschritten wird und dann abzuarbeiten. Dafuer laesst sich xargs gut benutzen. Wenn man z.B. maximal vier Prozesse haben moechte geht das mit:
find *.tif -print0 | xargs -0 -I {} -P 4 convert -compress JPEG {} {} |
find *.tif -print0 | xargs -0 -I {} -P 4 convert -compress JPEG {} {}
Dabei bedeuten die Parameter bei find:
- -print0 -> print the full file name on the standard output, followed by a null character
und bei xargs:
- -0 -> Input items are terminated by a null character instead of by whitespace
- -I {} -> Replace string
- -P 4 -> Run up to max-procs processes at a time
Der String replace wird genutzt um zweimal das gleiche Argument zu uebergeben. Arbeitet man mit -n 2 werden zwei aufeinanderfolgende Argumente uebergeben.