Führen Sie unter Linux mehrere JPGs zu einem einzigen PDF zusammen

73

Ich habe den folgenden Befehl verwendet, um alle jpgDateien in einem Verzeichnis in eine einzelne PDF-Datei zu konvertieren und zusammenzuführen .

convert *.jpg file.pdf

Die Dateien im Verzeichnis sind von 1.jpgbis nummeriert 123.jpg. Die Konvertierung verlief einwandfrei, aber nach der Konvertierung waren alle Seiten durcheinander. Ich wollte, dass das PDF Seiten von 1.jpgbis 123.jpgin derselben Reihenfolge enthält , in der sie benannt sind. Ich habe es auch mit folgendem Befehl versucht:

cd 1 
FILES=$( find . -type f -name "*jpg" | cut -d/ -f 2)
mkdir temp && cd temp 
for file in $FILES; do 
    BASE=$(echo $file | sed 's/.jpg//g');
    convert ../$BASE.jpg $BASE.pdf; 
    done && 
pdftk *pdf cat output ../1.pdf && 
cd .. 
rm -rf temp

Aber immer noch kein Glück. Betriebssystem Linux.

Harikrishnan
quelle
2
Hinzufügen eines Kommentars im Namen des Benutzers sindhus, der nicht über genügend Punkte zum Kommentieren verfügte (siehe unten): Der convertBefehl ist Teil des imagemagickPakets.
Teemu Leisti
1
Fehler: convert-im6.q16: Versuch, einen Vorgang auszuführen, der von der Sicherheitsrichtlinie "PDF" nicht zugelassen wird
Max N
Wenn Sie auf ein Problem mit Sicherheitsrichtlinien stoßen, lesen
Max N

Antworten:

19

Das Problem ist, dass Ihre Shell den Platzhalter in einer rein alphabetischen Reihenfolge erweitert und die Länge der Zahlen unterschiedlich ist. Die Reihenfolge ist falsch:

$ echo *.jpg
1.jpg 10.jpg 100.jpg 101.jpg 102.jpg ...

Die Lösung besteht darin, die Dateinamen nach Bedarf mit Nullen aufzufüllen, damit sie dieselbe Länge haben, bevor Sie den Befehl convert ausführen:

$ for i in *.jpg; do num=`expr match "$i" '\([0-9]\+\).*'`;
> padded=`printf "%03d" $num`; mv -v "$i" "${i/$num/$padded}"; done

Jetzt werden die Dateien vom Platzhalter in der richtigen Reihenfolge abgeglichen, bereit für den Konvertierungsbefehl:

$ echo *.jpg
001.jpg 002.jpg 003.jpg 004.jpg 005.jpg 006.jpg 007.jpg 008.jpg ...
Delan Azabani
quelle
Ich habe eine shDatei mit Ihrem Code erstellt. Aber es zeigt den folgenden Fehler während des Laufens:rename.sh: 2: rename.sh: Bad substitution
Harikrishnan
Verwenden Sie Bash? Wenn ja, welche Version?
Delan Azabani
GNU bash, version 4.2.24(1)-release (i686-pc-linux-gnu)
Harikrishnan
Wie führen Sie das Skript aus? Verwenden Sie sourceoder .oder mit einer Shebang-Linie? Haben Sie versucht, den Code einfach direkt in der interaktiven Shell auszuführen?
Delan Azabani
1
shist fast immer nicht dasselbe wie bash. Es ist normalerweise die einfache Bourne-Shell oder wird bashin einem speziellen Bourne-Emulationsmodus ausgeführt. In beiden Fällen kann die Syntax für shmanchmal sehr unterschiedlich sein. Ich würde vorschlagen, bash rename.shstattdessen zu verwenden.
Delan Azabani
114

Oder lesen Sie einfach das lsHandbuch und sehen Sie:

-v natürliche Art von (Versions-) Zahlen im Text

Also tun, was wir brauchen, in einem einzigen Befehl.

convert `ls -v *.jpg` foobar.pdf

Viel Spaß;) F.

Felix Defrance
quelle
1
@ Jason: Es funktioniert (+1). Aber haben Sie schließlich vergessen, dass die meisten Digitalkameras ihre Bilder als *.JPGund nicht als speichern *.jpg?
Martin Thoma
1
Schlägt fehl, wenn Dateinamen ein Leerzeichen enthalten, außer von diesem Daumen nach oben!
:)
3
Beachten Sie, dass dies eine Funktion von GNU ls ist, nicht von BSD ls. Installieren Sie GNU Coreutils, um GNU ls auf der BSD-Familie und OS X zu erhalten.
4ae1e1
3
Ein weiterer guter Punkt, wenn Sie Ihre Bilder in der richtigen Reihenfolge generiert haben, ist das Sortieren nach Änderungszeit mit ls -tFlag. Außerdem -rkehrt das Flag die Reihenfolge um.
Spelufo
4
Dies ist eine ausgezeichnete Lösung. Als ich es versuchte, schlug es jedoch aufgrund dieses Fehlers convert-im6.q16: not authorized fehl : foobar.pdf'`. Offensichtlich ist dies ein Sicherheitsproblem, das über diesen Thread behoben werden
Scott
4

So mache ich das: In der
ersten Zeile konvertieren Sie alle JPG-Dateien in PDF, wobei der Befehl convert verwendet wird.
In der zweiten Zeile werden alle PDF-Dateien zu einer einzigen PDF-Datei pro Seite zusammengeführt. Dies verwendet gs ((PostScript- und PDF-Sprachinterpreter und Previewer))

for i in $(find . -maxdepth 1 -name "*.jpg" -print); do convert $i ${i//jpg/pdf}; done
gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=merged_file.pdf -dBATCH `find . -maxdepth 1 -name "*.pdf" -print"`
Marsmensch
quelle
4

Du könntest benutzen

convert '%d.jpg[1-132]' file.pdf

über https://www.imagemagick.org/script/command-line-processing.php :

Eine andere Methode zum Verweisen auf andere Bilddateien besteht darin, ein Formatierungszeichen mit einem Szenenbereich in den Dateinamen einzubetten. Betrachten Sie den Dateinamen image-%d.jpg[1-5]. Der Befehl

magick image-%d.jpg[1-5] veranlasst ImageMagick, Bilder mit folgenden Dateinamen zu lesen:

image-1.jpg image-2.jpg image-3.jpg image-4.jpg image-5.jpg

Siehe auch https://www.imagemagick.org/script/convert.php

Lukas
quelle
3

Alle oben genannten Antworten sind für mich fehlgeschlagen, als ich viele hochauflösende JPEG-Bilder (aus einem gescannten Buch) zusammenführen wollte.

Imagemagick hat versucht, alle Dateien in den Arbeitsspeicher zu laden. Daher habe ich den folgenden zweistufigen Ansatz verwendet:

find -iname "*.JPG" | xargs -I'{}' convert {} {}.pdf
pdfunite *.pdf merged_file.pdf

Beachten Sie, dass Sie bei diesem Ansatz GNU auch parallel verwenden können, um die Konvertierung zu beschleunigen:

find -iname "*.JPG" | parallel -I'{}' convert {} {}.pdf
Gregor Sturm
quelle
0

Wenn ich die erste Idee mit ihrer Antwort mische, denke ich, dass dieser Code vielleicht zufriedenstellend ist

jpgs2pdf.sh

#!/bin/bash

cd $1
FILES=$( find . -type f -name "*jpg" | cut -d/ -f 2)
mkdir temp > /dev/null
cd temp

for file in $FILES; do
 BASE=$(echo $file | sed 's/.jpg//g');
 convert ../$BASE.jpg $BASE.pdf;
done &&

pdftk `ls -v *pdf` cat output ../`basename $1`.pdf
cd ..
rm -rf temp
Juan Lagos
quelle