将多个图像文件从 JPEG 转换为 PDF 格式

Pra*_*are 62 command-line imagemagick wildcards conversion

我想将一些文件从 jpeg 转换为 pdf。我正在使用以下命令。

$ convert image1.jpg image1.pdf 
Run Code Online (Sandbox Code Playgroud)

但我有 100 张图片。我应该如何将它们全部转换为相应的 pdf?

我试过

$ convert image*.jpg image*.pdf 
Run Code Online (Sandbox Code Playgroud)

它不起作用。

enz*_*tib 73

在 bash 中:

for f in *.jpg; do
  convert ./"$f" ./"${f%.jpg}.pdf"
done
Run Code Online (Sandbox Code Playgroud)

  • @rahmu:是的,这是一个很好的做法,因为以`-` 开头的文件名会出现问题,否则。 (5认同)
  • 这是有效的,但是 `mogrify` 的输入要少得多。看我的回答。 (3认同)
  • 您在转换参数前添加“./”的任何特殊原因?这是一个普遍的良好做法吗? (2认同)

cjm*_*cjm 66

您可以mogrify为此使用该命令。通常,它会就地修改文件,但在转换格式时,它会写入一个新文件(只需更改扩展名以匹配新格式)。因此:

mogrify -format pdf -- *.jpg
Run Code Online (Sandbox Code Playgroud)

(与 enzotib 的 一样./*.jpg,它--可以防止任何奇怪的文件名被解释为开关。大多数命令都识别--为“此时停止寻找选项”。)


Seb*_*ian 26

更快但不寻常的语法:

parallel convert '{} {.}.pdf' ::: *.jpg
Run Code Online (Sandbox Code Playgroud)

并行运行(使用https://www.gnu.org/software/parallel/)。我还没有注意到任何多线程convert,这会限制有效的并行化。如果这是您的担忧,请参阅下面的评论以获取确保不发生多线程的方法。

  • 在这里参加聚会有点晚了,但是 ImageMagick 的新版本(可能不是在编写此答案时)是多线程的,如果并行运行,交互会很糟糕。这可以通过设置环境变量“MAGICK_THREAD_LIMIT=1”来禁用(如果使用应用程序级并行化,例如使用 GNU `parallel`)。 (3认同)

Rob*_*ing 23

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

在所有涉及 ImageMagick 的建议解决方案中,JPEG 数据都被完全解码和重新编码。这会导致代损失,以及性能比img2pdf.

自 Debian 9 (stretch) 起在 Debian 中可用,自 16.04 (xenial) 起在 Ubuntu 中可用。也可以安装,pip img2pdf前提是您有依赖项(例如apt-get install python python-pil python-setuptools libjpeg-devyum install python python-pillow python-setuptools)。

  • `img2pdf` 可在 Ubuntu 16.04 常规存储库中使用,无需在那里使用 `pip` 进行手动操作,并且您可以保留更新的好处。 (4认同)
  • 是对的。您可以使用诸如 `convert some.jpg -format pdf -compress jpeggenerated.pdf 之类的命令来测试往返更改 JPEG 文件;pdfimages -j 生成.pdf 生成.pdf ; diff -sq some.jpg 生成.pdf-000.jpg`。恕我直言,这个答案值得更多赞成。事实上,`convert` 在这里失败了,`img2pdf` 通过了这样的测试,甚至包括许多选项来设置图片大小、页面大小等,以根据您的需要微调生成的 pdf。 (3认同)
  • 在提出问题(并接受答案)时,img2pdf 不存在。但现在 img2pdf 显然是一个更好的答案。 (2认同)

acu*_*ich 13

这是一种将上述建议的最佳组合成一个简单、高效、健壮的命令行的方法:

find /path/to/files -iname '*.jpg' -exec mogrify -format pdf {} +
Run Code Online (Sandbox Code Playgroud)

它适用于以 a-或包含空格开头的文件名。请注意-inamewhich的使用是不区分大小写的版本,-name因此它将.JPG.jpg.

这用于find获取文件列表,而不是使用*.jpg通配符进行 shell通配,这可能会在某些系统上导致“参数列表太长”错误。尽管@enzotib 在评论中指出,在 for 循环中使用globbing 的行为与命令的 arguments 不同

此外,find将处理子目录,而 shell globbing 不会,除非您碰巧具有特定于 shell 的功能,例如**/*jpgzsh 中的递归 globbing 语法。

编辑:我想我会find在阅读@IlmariKaronen关于重新运行命令并只转换自第一次运行后更改的文件的评论后想到的另一个有用的功能。

在第一次通过时,您可以touch在转换完成后获得时间戳文件。

find /path/to/files -iname '*.jpg' -exec mogrify -format pdf {} +; touch timestamp
Run Code Online (Sandbox Code Playgroud)

然后添加-newer timestampfind表达式以对最后修改时间比时间戳文件新的文件子集进行操作。每次运行后继续更新时间戳文件。

find /path/to/files -iname '*.jpg' -newer timestamp -exec mogrify -format pdf {} +; touch timestamp
Run Code Online (Sandbox Code Playgroud)

这是一种避免不得不求助于 Makefile 的简单方法(除非您已经在使用它),这也是它值得find尽可能使用的另一个很好的理由……它具有多功能的表现力,同时保持简洁。


小智 9

您可以convert直接执行此操作。这可以在 ImageMagicks 站点关于命令行处理的底部找到。

convert *.jpg +adjoin page-%d.pdf
Run Code Online (Sandbox Code Playgroud)

  • 或 `convert *.jpg -adjoin output.pdf` 用于合并的 pdf (6认同)
  • 为此使用 ImageMagick 会导致生成损失和性能不佳。本页其他地方的 img2pdf 避免了这些问题。 (2认同)

ret*_*eto 8

我已经将以下 makefile 用于类似的东西:

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

all: $(PNG)

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


clean: 
    rm $(PNG)
Run Code Online (Sandbox Code Playgroud)

现在我可以运行make并为周围的每个 svg 文件获取 png 文件。

编辑

按照要求:

  • 通配符生成 origs/ 中所有 svgs 的列表
  • pathsubst 获取此列表并生成一个 png 文件名列表(不同的文件夹和扩展名。示例:origs/foo.svg变成foo.png
  • 规则 1:all: $(PNG)定义目标“all”取决于所有 PNG
  • 规则二:%.png: origs/%.svg定义,文件$X.png依赖于origs/$X.svg,可以通过调用生成convert ... $< $@
    • $< 是依赖和和
    • $@ 是目标名称
  • 规则 3:只是为了清理

  • 对于一次性任务,创建 Makefile 可能有点过头了,但是如果您打算更改某些 PDF,再次键入 `make` 将重新转换那些,并且_仅_那些已更改的 PDF。 (2认同)