67

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.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
Pratik Deoghare
  • 1,217
  • 1
  • 11
  • 16
  • Related: [How to generate a PDF from a series of images?](http://superuser.com/q/687849/87805) at superuser SE – kenorb Feb 26 '15 at 16:02
  • See also: [AskUbuntu: Create a single pdf from multiple text, images or pdf files](https://askubuntu.com/q/303849/327339). If you'd also like your resulting PDF to be searchable via OCR (Optical Character Recognition) on the text in the input images, use [my `pdf2searchablepdf` tool I describe here](https://askubuntu.com/a/1385947/327339), which can also convert an entire directory of images into a single, searchable PDF. – Gabriel Staples Jan 08 '22 at 07:15

13 Answers13

77

In bash:

for f in *.jpg; do
  convert ./"$f" ./"${f%.jpg}.pdf"
done
enzotib
  • 50,671
  • 14
  • 120
  • 105
  • 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?](http://unix.stackexchange.com/questions/20681/why-for-loop-doesnt-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](http://unix.stackexchange.com/a/29875/11052) 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
  • 27,777
  • 43
  • 130
  • 199
cjm
  • 26,740
  • 12
  • 88
  • 84
  • +1, my answer was only about bash, don't know well ImageMagick. – enzotib Jan 24 '12 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`](http://unix.stackexchange.com/a/30420/11052). – aculich Jan 30 '12 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. – nutty about natty Jul 21 '13 at 07:40
  • as a workaround: converting all `*.jpg`'s into `*.png`'s in step one, and performing the equivalent of your answer in step 2... – nutty about natty Jul 21 '13 at 07:46
  • see also http://stackoverflow.com/questions/15315770/how-to-convert-all-files-in-different-formats-in-given-folder-to-different-fil – nutty about natty Jul 21 '13 at 07:48
  • @nuttyaboutnatty, that's a new question, not a comment. Ask it. – cjm Jul 21 '13 at 15:46
  • 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
  • -1 `mogrify mogrify: Unrecognized option (--).` – Shautieh Apr 14 '17 at 11:31
  • Any way to do it recursively? – mrgloom Nov 02 '18 at 18:35
  • This gives me: `mogrify-im6.q16: attempt to perform an operation not allowed by the security policy `PDF' @ error/constitute.c/IsCoderAuthorized/408.` On Devuan Beowulf. – einpoklum Dec 11 '20 at 17:01
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,677
  • 4
  • 39
  • 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).

Robert Fleming
  • 457
  • 4
  • 9
  • 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
  • 10
  • 14
  • 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
Frank Zalkow
  • 199
  • 1
  • 3
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
  • 537
  • 3
  • 9
  • 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](http://unix.stackexchange.com/a/30420/11052) 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](http://unix.stackexchange.com/a/30420/11052) 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
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
  • 55,929
  • 26
  • 146
  • 227
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
  • 19,673
  • 28
  • 87
  • 128
  • `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. – Gilles 'SO- stop being evil' Jan 24 '12 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](http://unix.stackexchange.com/a/30420/11052). – aculich Jan 30 '12 at 23:02
1

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
  • 119
  • 2
  • 6
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).

John Sidles
  • 111
  • 3
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  
Eduard Florinescu
  • 11,153
  • 18
  • 57
  • 67
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
Patrick Mevzek
  • 3,130
  • 2
  • 20
  • 30