Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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.

share|improve this question
add comment

8 Answers

up vote 24 down vote accepted

In bash:

for f in *.jpg; do
  convert ./"$f" ./"${f%.jpg}.pdf"
done
share|improve this answer
    
Any particular reason why you prepend "./" to the args of convert? Is it a general good practice? –  rahmu Jan 24 '12 at 10:46
1  
@rahmu: yes, it is a good practice, because filename beginning with - give problems, otherwise. –  enzotib Jan 24 '12 at 10:48
1  
This works, but mogrify is a lot less typing. See my answer. –  cjm Jan 24 '12 at 12:04
    
+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 5:27
show 2 more comments

https://github.com/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.

share|improve this answer
add comment

faster and less painful syntax:

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

Runs in parallel (using https://www.gnu.org/software/parallel/).

share|improve this answer
    
This way is full of win. It auto assess core count and runs that many tasks! –  meawoppl Oct 27 '13 at 21:52
add comment

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.

share|improve this answer
add comment

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

share|improve this answer
add comment

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.

share|improve this answer
    
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 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. –  aculich Jan 30 '12 at 23:02
add comment

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
share|improve this answer
    
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 1 '12 at 5:23
    
I even get downvotes, this answer must be really bad. It's clearly not even a little bit interestig for cases where the conversions might a bit a tad more complex. Anyway... –  reto Feb 1 '12 at 22:44
add comment

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".)

share|improve this answer
    
+1, my answer was only about bash, don't know well ImageMagick. –  enzotib Jan 24 '12 at 12:57
    
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 '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 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... –  nutty about natty Jul 21 '13 at 7:46
    
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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