It's known that images can be converted to one single pdf with the following command (assuming images filenames are order correctly):

convert *.jpg output.pdf.

However, this approach may take too much RAM when it involves thousands images. Another idea would be converting images to pdf by batches, then concatenate the resulted pdf to a single one with pdftk:

pdftk output-*.pdf cat output output.pdf

So far, I tried to batch convert images with xargs:

ls *.jpg | xargs -d $'\n' -t -n 100 bash -c 'convert "$@" output.pdf'

It works well except that each time, convert erases the previous pdf.

Question: Is there a way to count the batch number, and produce successively, for instance, output-1.pdf, ..., output-9.pdf ?


If you're able to swap xargs for GNU parallel, that does provide a {#} replacement string containing the sequence number being run.

So for example given

$ touch File{001..050}.jpg


$ printf '%s\0' *.jpg | parallel --null -n 5 echo convert {} -o output{#}.pdf
convert File001.jpg File002.jpg File003.jpg File004.jpg File005.jpg -o output1.pdf
convert File006.jpg File007.jpg File008.jpg File009.jpg File010.jpg -o output2.pdf
convert File011.jpg File012.jpg File013.jpg File014.jpg File015.jpg -o output3.pdf
convert File016.jpg File017.jpg File018.jpg File019.jpg File020.jpg -o output4.pdf
convert File021.jpg File022.jpg File023.jpg File024.jpg File025.jpg -o output5.pdf
convert File026.jpg File027.jpg File028.jpg File029.jpg File030.jpg -o output6.pdf
convert File031.jpg File032.jpg File033.jpg File034.jpg File035.jpg -o output7.pdf
convert File036.jpg File037.jpg File038.jpg File039.jpg File040.jpg -o output8.pdf
convert File041.jpg File042.jpg File043.jpg File044.jpg File045.jpg -o output9.pdf
convert File046.jpg File047.jpg File048.jpg File049.jpg File050.jpg -o output10.pdf
  • 1
    Thanks, this is what I was looking for, plus it's faster and concise. Nov 1 '20 at 20:20

xargs doesn't provide a way to count the current instance. You could do ls *.jpg | xargs -d $'\n' -t -n 100 bash -c 'convert "$@" output-$$.pdf' to get different names, but then you'd have to figure out the order based on the file timestamp.

A solution would be to progressively combine them:

ls *.jpg  |  xargs -d $'\n' -t -n 100 bash -c 'convert "$@" temp.pdf'; if [ -f output.pdf ]; then mv temp.pdf next.pdf; pdftk output.pdf next.pdf cat output temp.pdf; fi; mv temp.pdf output.pdf`

Although I think the best way for this would be to just convert each image individually:

find -name \*.jpg -exec convert \{\} \{\}.pdf \;
pdftk *.jpg.pdf cat output output.pdf

It's simpler, and cost of converting every image on a separate process would be roughly equivalent to having one convert instance processing N of them.

Plus, if it happens that one of the images isn't actually ordered, it's simpler to rearrange, rather than having to reconvert every image since the batches now changed.

  • Ah, you're right and that's what I used to do actually. Probably was obsessed to write a one-liner. Thanks! Nov 1 '20 at 0:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.