68

I want to convert some files from jpeg to pdf. I am using following command.

$ convert image1.jpg image1.pdf 

But I have 100 images. How should I convert all of them to corresponding pdfs?

I tried

$ convert image*.jpg image*.pdf 

It doesn't work.

2

13 Answers 13

78

In bash:

for f in *.jpg; do
  convert ./"$f" ./"${f%.jpg}.pdf"
done
10
  • 2
    Any particular reason why you prepend "./" to the args of convert? Is it a general good practice?
    – rahmu
    Jan 24, 2012 at 10:46
  • 6
    @rahmu: yes, it is a good practice, because filename beginning with - give problems, otherwise.
    – enzotib
    Jan 24, 2012 at 10:48
  • 3
    This works, but mogrify is a lot less typing. See my answer.
    – cjm
    Jan 24, 2012 at 12:04
  • 1
    +1 because this is technically correct and avoids bash pitfalls, but -1 because mogrify is the Imagemagick way to batch convert images. So no vote from me.
    – Benoit
    Jan 24, 2012 at 12:41
  • @aculich: thank you for your downvote, but you did a wrong consideration, see why for loop doesn't raise “argument too long” error?.
    – enzotib
    Jan 31, 2012 at 5:27
66

You can use the mogrify command for this. Normally, it modifies files in-place, but when converting formats, it writes a new file (just changing the extension to match the new format). Thus:

mogrify -format pdf -- *.jpg

(Like enzotib's ./*.jpg, the -- prevents any strange filenames from being interpreted as switches. Most commands recognize -- to mean "stop looking for options at this point".)

10
  • +1, my answer was only about bash, don't know well ImageMagick.
    – enzotib
    Jan 24, 2012 at 12:57
  • 1
    Good idea to use mogrify instead of convert. This will work for 100 files, but using globbing with *.jpg does not scale to thousands of files; that can be done by combining the command in a simple one-liner with find.
    – aculich
    Jan 30, 2012 at 23:08
  • How to convert both *.jpg and *.png files to a single *.pdf? Note that they are numbered files (e.g., 1.jpg 2.png 3.png 4.jpg) and that order should be maintained/preserved in the pdf output. Jul 21, 2013 at 7:40
  • as a workaround: converting all *.jpg's into *.png's in step one, and performing the equivalent of your answer in step 2... Jul 21, 2013 at 7:46
  • see also stackoverflow.com/questions/15315770/… Jul 21, 2013 at 7:48
26

faster but unusual syntax:

parallel convert '{} {.}.pdf' ::: *.jpg

Runs in parallel (using https://www.gnu.org/software/parallel/). I haven't noticed any multi-threading in convert yet, which would limit the effective parallelization. If that is your concern, see in the comment below for a method to ensure no multi-threading occurs.

6
  • 1
    This way is full of win. It auto assess core count and runs that many tasks!
    – meawoppl
    Oct 27, 2013 at 21:52
  • 1
    This method is THE fastest of all.
    – shivams
    May 7, 2015 at 6:10
  • 1
    parallel is power, parallel combined with imagemagick is superpower. I like superpower. Aug 11, 2015 at 10:11
  • 3
    A bit late to the party here, but new (possibly not when this answer was written) versions of ImageMagick are multi-threaded, and will interact badly if run in parallel. This can be disabled (if using application-level parallelization such as with GNU parallel) by setting the environment variable MAGICK_THREAD_LIMIT=1.
    – zebediah49
    Sep 4, 2015 at 3:58
  • 1
    Using ImageMagick for this results in generation loss and poor performance. img2pdf elsewhere on this page avoids those problems. Jul 23, 2016 at 17:24
26

https://gitlab.mister-muffin.de/josch/img2pdf

In all of the proposed solutions involving ImageMagick, the JPEG data gets fully decoded and re-encoded. This results in generation loss, as well as performance "ten to hundred" times worse than img2pdf.

Available in Debian since Debian 9 (stretch) and Ubuntu since 16.04 (xenial). Also can be installed with pip img2pdf provided you have dependencies (e.g. apt-get install python python-pil python-setuptools libjpeg-dev or yum install python python-pillow python-setuptools).

4
  • 3
    is right. You can test that a roundtrip changes a JPEG file with commands like convert some.jpg -format pdf -compress jpeg generated.pdf ; pdfimages -j generated.pdf generated.pdf ; diff -sq some.jpg generated.pdf-000.jpg. IMHO this answer deserves more upvotes. Indeed, convert fails here, img2pdf passes such a test and even includes many options to set picture size, page size, etc to finetune the generated pdf to your needs. Jul 21, 2016 at 7:14
  • 4
    img2pdf is available in Ubuntu 16.04 regular repositories, no need for manual operations with pip there, and you keep the benefit of updates. Jul 21, 2016 at 7:15
  • 2
    At the time the question was asked (and answer accepted) img2pdf did not exist. But nowdays img2pdf is clearly a better answer.
    – kmkaplan
    Jan 19, 2017 at 14:58
  • img2pdf is an order of magnitude better than convert Jan 21, 2021 at 11:17
14

Here is a way that combines the best of the above suggestions into a simple, efficient, robust command line:

find /path/to/files -iname '*.jpg' -exec mogrify -format pdf {} +

It works fine with filenames that begin with a - or contain spaces. Note the use of -iname which is the case-insensitive version of -name so it will work on .JPG just as well as .jpg.

This uses find to get the file list instead of shell globbing with the *.jpg wildcard which can result in an 'Argument list too long' error on some systems. Though as @enzotib points in a comment, behavior of using globbing in a for loop is different than for a command's arguments.

Also, find will handle subdirectories, whereas shell globbing will not unless you happen to have shell-specific features like the **/*jpg recursive globbing syntax in zsh.

EDIT: I thought I would add another useful feature of find that I thought of after reading a comment by @IlmariKaronen about re-running the command and only converting files that have changed since the first run.

On the first pass you can touch a timestamp file after the convert is finished.

find /path/to/files -iname '*.jpg' -exec mogrify -format pdf {} +; touch timestamp

Then add -newer timestamp to the find expression to operate on the subset of files whose last-modified time is newer than the timestamp file. Continue updating the timestamp file after each run.

find /path/to/files -iname '*.jpg' -newer timestamp -exec mogrify -format pdf {} +; touch timestamp

This is an easy way to avoid having to resort to a Makefile (unless you're already using one) and it is another good reason why it is worth using find whenever possible... it has versatile expressiveness while remaining concise.

1
  • Using ImageMagick for this results in generation loss and poor performance. img2pdf elsewhere on this page avoids those problems. Jul 23, 2016 at 17:24
9

You can do this with convert directly. This is to be found at the bottom of ImageMagicks Site about Command Line Processing.

convert *.jpg +adjoin page-%d.pdf
2
  • 6
    or convert *.jpg -adjoin output.pdf for a combined pdf
    – ninjagecko
    Jul 10, 2014 at 18:42
  • 2
    Using ImageMagick for this results in generation loss and poor performance. img2pdf elsewhere on this page avoids those problems. Jul 23, 2016 at 17:24
8

I've used the following makefile for something similar:

SVG = $(wildcard origs/*.svg)
PNG = $(patsubst origs/%.svg,%.png,$(SVG))

all: $(PNG)

%.png: origs/%.svg
    convert -resize "64x" $< $@


clean: 
    rm $(PNG)

Now I can just run make and I get png files for every svg file that lies around.

Edit

As requested:

  • wildcards generates a list of all svgs in origs/
  • pathsubst takes this list and produces a list of png file names (different folder and extension. Example: origs/foo.svg becomes foo.png)
  • Rule 1: all: $(PNG) defines, that the target "all" depends on all PNGs
  • Rule 2: %.png: origs/%.svg defines, thethe file $X.png depends on origs/$X.svg and can be generated by calling convert ... $< $@.
    • $< is the dependency and and
    • $@ is the target name
  • RUle 3: is just for cleaning up
4
  • 2
    For a one-off task, creating a Makefile is probably overkill, but if you ever plan to change some of the PDFs, typing make again will reconvert those, and only those, PDFs which have changed. Jan 24, 2012 at 20:04
  • Would you mind to explain what wildcard, origs, patsubst is, how $ and % are interpreted and $< $@? The rest is easy to understand. :) Jan 24, 2012 at 22:46
  • Resorting to make seems a little over-complicated when a simple one-liner will do the trick.
    – aculich
    Jan 30, 2012 at 23:06
  • @IlmariKaronen I agree that a Makefile is overkill, but it is nice to have a way to reconvert only the subset of modified files on subsequent runs. I've updated my answer with a way to do that just with find so you don't have to resort to a Makefile.
    – aculich
    Feb 1, 2012 at 5:23
2

If you use only image files than maybe you would like to use Comic Book Archive (.cbr, .cbz, .cbt, .cba, .cb7)

  • If you use 7Z then rename the file extension (suffix) to .cb7
  • If you use ACE then rename the file extension (suffix) to .cba
  • If you use RAR then rename the file extension (suffix) to .cbr
  • If you use TAR then rename the file extension (suffix) to .cbt
  • If you use ZIP then rename the file extension (suffix) to .cbz

This is much more flexible than PDF.

Under Linux you can use software like Comix, Evince, Okular and QComicBook.

https://secure.wikimedia.org/wikipedia/en/wiki/Comic_book_archive

1
  • 1
    downvoted, because it has nothing to do with the OP's question.
    – uuu
    May 28, 2016 at 14:55
1

A tiny script would do the trick. (tested with ksh88 on Solaris 10)

script.ksh

#!/bin/ksh

[[ $# != 1 ]] && exit 255 # test for nr of args

pdfname=$(sed -e 's/\(.*\)\.jpg/\1\.pdf/' <(echo $"1")) #replace *.jpg with *.pdf
convert "$1" $pdfname

Then you can run find to execute the script:

find dir -name image\*.jpg -exec /bin/ksh script.ksh {} \;

Note that both script.ksh and the find command I gave you, might have different syntaxes depeding on the OS and the shell you are using.

2
  • pdfname=${1%.*}.pdf replaces the file's extension with pdf. That method is a lot simpler and works even if the file name contains special characters. On a related note, add double quotes around variable substitutions. Jan 24, 2012 at 17:51
  • There is no reason to write a separate script when it can all be done on the with a simple single command line.
    – aculich
    Jan 30, 2012 at 23:02
1

The MacOS utility SIPS  Under MacOS (Sierra), Apple's built-in command-line utility sips provides comprehensive access to all of Apple's raster-image utilities; this turns out to include the conversion of jpg to pdf.

For example, from an existing low-resolution/small-size jpg image 'cat.jpg' (of size 8401 bytes), the following command-line creates 'cat.pdf', with no change in raster-resolution and minimal expansion of file size:

$ sips -s format pdf cat.jpg --out 'cat.pdf' 1>/dev/null 2>&1
$ ls -l cat.*
-rw-r--r--@ 1 <user redacted> <group redacted>  8401 Jun 18 07:06 cat.jpg
-rw-r--r--+ 1 <user redacted> <group redacted> 10193 Jun 18 07:22 cat.pdf

Conversion to Adobe's PSD raster-image format  A similar sips idiom creates Adobe-compatible *.psd files

$ sips -s format psd cat.jpg --out 'cat.psd' 1>/dev/null 2>&1
$ ls -l cat.jpg cat.psd
-rw-r--r--@ 1 Administration  staff    8401 Jun 18 07:06 cat.jpg
-rw-r--r--+ 1 Administration  staff  350252 Jun 18 07:37 cat.psd

Note however the 30-fold file-size expansion that is attendant to the use of the Adope psd raster-format.

Book Production  In doing large-scale book production, involving hundreds of images, that are supplied in multiple formats, for me a convenient command-line idiom has been use ImageMagick utilities to create pure raster-image files in png format (with all meta-data and color profiles stripped-out), then use sips to restore a uniform set of color profiles and/or comments, and use sips also to generate final output files (most commonly *.png, *.psd, or *.pdf files).

1

Unfortunately convert changes the image before so to have minimal loss of quality of the original jpg you need to use img2pdf, I use this commands:

1) This to make a pdf file out of every jpg image without loss of either resolution or quality:

ls -1 ./*jpg | xargs -L1 -I {} img2pdf {} -o {}.pdf

2) This to concatenate the pdfpages into one:

pdftk *.pdf cat output combined.pdf

3) And last I add an OCRed text layer that doesn't change the quality of the scan in the pdfs so they can be searchable:

pypdfocr combined.pdf  
1

I got solve with imagemagick for conversion and parallel to accelerate my conversion process:

ls *.JPEG |parallel convert -density 200 -resize 496X646 -quality 100 {}  ../{.}.PDF
1

One of the simplest way to convert multiple files is to go to the file directory in linux terminal and type:

$ convert *.png mypdf.pdf

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .