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.

13 Answers13

78

In bash:

for f in *.jpg; do
  convert ./"$f" ./"${f%.jpg}.pdf"
done
enzotib
  • 51,661
  • 2
    Any particular reason why you prepend "./" to the args of convert? Is it a general good practice? – rahmu Jan 24 '12 at 10:46
  • 6
    @rahmu: yes, it is a good practice, because filename beginning with - give problems, otherwise. – enzotib Jan 24 '12 at 10:48
  • 3
    This works, but mogrify is a lot less typing. See my answer. – cjm Jan 24 '12 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 '12 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 '12 at 05:27
  • @enzotib ah, thanks for pointing that out. I was not aware that it behaved differently in a for loop. I have removed my erroneous comment, but that was not the only reason I down-voted. The mogrify command as cjm suggests is much simpler and find is more versatile since it can handle directory hierarchies (you can do recursive globbing with **/*.jpg in zsh, but that is shell-specific, whereas find is not) and it is easy to make find case-insensitive with -iname instead of -name, which is harder to do and shell-specific for globbing. – aculich Jan 31 '12 at 16:31
  • @enzotib Also with find you do not have problems with filenames that begin with -, so there is no need for adding ./ like you must with the shell for loop. – aculich Jan 31 '12 at 16:37
  • @jiggunjer it will not let me remove my old downvote because the post has already been edited. my vote was a technical vote based on incorrect assumption about * on my part, not a political vote. – aculich Dec 25 '15 at 13:02
  • Using ImageMagick for this results in generation loss and poor performance. img2pdf elsewhere on this page avoids those problems. – Robert Fleming Jul 23 '16 at 17:26
  • @RobertFleming: the question was not on the choice of the tool, but on the automatic management of a lot of files, so I used the same tool ("convert") proposed in the question and concentrate on the scripting. – enzotib Jul 24 '16 at 14:42
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".)

rubo77
  • 28,966
cjm
  • 27,160
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.

Sebastian
  • 8,817
  • 4
  • 40
  • 49
  • 1
    This way is full of win. It auto assess core count and runs that many tasks! – meawoppl Oct 27 '13 at 21:52
  • 1
    This method is THE fastest of all. – shivams May 07 '15 at 06:10
  • 1
    parallel is power, parallel combined with imagemagick is superpower. I like superpower. – CousinCocaine Aug 11 '15 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 04 '15 at 03:58
  • 1
    Using ImageMagick for this results in generation loss and poor performance. img2pdf elsewhere on this page avoids those problems. – Robert Fleming Jul 23 '16 at 17:24
  • Interesting project, Robert, thanks for the pointer – Sebastian Jul 23 '16 at 21:08
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).

  • 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. – Stéphane Gourichon Jul 21 '16 at 07: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. – Stéphane Gourichon Jul 21 '16 at 07: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 '17 at 14:58
  • img2pdf is an order of magnitude better than convert – étale-cohomology Jan 21 '21 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.

aculich
  • 1,180
  • Using ImageMagick for this results in generation loss and poor performance. img2pdf elsewhere on this page avoids those problems. – Robert Fleming Jul 23 '16 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
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
reto
  • 557
  • 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. – Ilmari Karonen Jan 24 '12 at 20:04
  • Would you mind to explain what wildcard, origs, patsubst is, how $ and % are interpreted and $< $@? The rest is easy to understand. :) – user unknown Jan 24 '12 at 22:46
  • Resorting to make seems a little over-complicated when a simple one-liner will do the trick. – aculich Jan 30 '12 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 01 '12 at 05: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

jojo
  • 129
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
Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232
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.

rahmu
  • 20,023
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

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