Reordering large PDF files using command line tools - pdf

I'm working with PDF files that have hundreds of forms within them. Each form is 2 pages long, so in most files pages 1-2 is the first form, pages 3-4 is the second form, and so on.
However, there are several PDF files where the page order of the forms are reversed. In these cases, page 1 is the second page of the first form and page 2 is the first page of the first form, page 3 is the second page of the second form and page 4 is the first page of the second form, and so on.
I want to reorder the page order in these files so that the pages are in this sequence: (2(1), 2(1)-2, 2(2), 2(2)-1, 2(3), 2(3)-1,...,2n,2n-1), where n= total number of pages/2.
I've been looking for a way to do this using command line tools such as cpdf, pdftk, etc., but to no avail. The files are quite large so I would like to do it by using command line tools.
Any advice will be greatly appreciated!

CIB pdf toolbox of CIB (https://www.cib.de) has a (non free) command line tool version, which supports all possibilities of PDF merging in one run.
Did you try poppler-utils?
i think with the command line tools pdfseparate and pdfunite utilities you can achieve all you want.
http://www.manpagez.com/man/1/pdfseparate/
http://www.manpagez.com/man/1/pdfunite/

Would it matter to you if the order of the forms inside the PDF is changed? For example if instead of
form1-reversed,
form2-reversed,
form3-reversed
your resulting file would look like
form3,
form2,
form1
?
In this case you could just run PDFtk so that it completely reverses all the pages of the original file:
pdftk in.pdf cat r1-1 output reversed.pdf
(Prefixing a page number with the letter r references pages in reverse order. That means r1 is the last page...)

In case you are on an operating system which supports shell scripting (like Bash on Linux or macOS), you can achieve the output of your requested page numbers by something like this (assuming that your n==10):
for i in {1..10}; do
echo -n "$(( 2 * ${i} )) ";
echo -n "$(( 2 * ${i} -1 )) ";
done
This will output 2 1 4 3 6 5 8 7 10 9. Now you could use this PDFtk command for re-ordering the pages as you want:
pdftk in.pdf cat $(for i in {1..10};do echo -n "$((2 * ${i})) ";echo -n "$((2*${i}-1 )) ";done) output out.pdf

Related

Ghostscript merging ps and pdf files into pdf

I am trying to merge some pages of a postscript file 'A' (pages 1 to 3) and all pages of 'B' pdf file and some pages of the same postscript file 'A' (Pages 4 to 5) and all pages of 'C' PDF into one pdf.
Command is executed but same pages from 'A' (Pages 1 to 3) ps file is appended to final output instead of Pages 4 to 5 of 'A'.
Below is my gs command
gswin32c -dNOPAUSE -dSAFER -dBATCH -sOutputFile=out.pdf -sDEVICE=pdfwrite -sPageList=1-3 ghi-21.ps -sPageList=1-5 bf1ypage4-8.pdf -sPageList=4-5 ghi-21.ps -sPageList=1- bfpage11-37.pdf
Here File 'A' is ghi-21.ps (Total Pages 5)
File 'B' is bf1ypage4-8.pdf (Total Pages 5)
File 'C' is bfpage11-37.pdf (Totao Pages 27)
My Out.pdf should be like File 'A' Pages - 1 to 3 + File 'B' all Pages + File 'A' Pages 4 to 5 + File 'C' all Pages
On looking at the Manual there are restrictions on combining inputs.
Apparently according to KenS (2016) https://stackoverflow.com/a/40319742/10802527 we are lucky to be getting any merged output at all !
"you cannot process pages out of order" (so no skipping to and fro.) Ghostscript -sPageList produces stackunderflow error and quits
"PageList overrides FirstPage and/or LastPage"
"PDF files enable random access to pages"
"PCL and PostScript cannot be handled in ths[sic] way,...sending multple[sic] files as input on the command line does not reset the PageList between each document,"
Finally says
"This means you must exercise caution when using this switch, and probably should not use it at all when processing a mixture of PostScript and PDF files on the same command line."

phpseclib: "CAT" command works randomly

I have a script that fetches data from a site.
Basically it is divided into two section.
1.executes commands on a remote machine and saves output in a file
2.read the contents of a file.
For some reason it works from time to time. Section 1 always works (checked the remote machine and found the files). The problem is related to cat.
I've added to my code the option to dump the results of "CAT" command to a file.
Sometimes it has info sometimes it doesn't. However the file is always created!
The nodes i'm querying are the same. Timeout of execution of Section 1 on a remote server is 11-12 secs.
Thanks beforehand.
$ssh->exec("rm toolkit/mybatch/$newfileid");
$ssh->exec("mobatch $newsiteid 'lt all;ue print -admitted;' toolkit/mybatch");
$ssh->setTimeout(15);
echo $ssh->exec('cat ' . escapeshellarg("toolkit/mybatch/$newfileid") . '| grep -A 10 \'$ ue print \' > toolkit/mybatch/traffic.txt');
$traffic = $ssh->exec("cat toolkit/mybatch/traffic.txt");
$traffic = substr($traffic,21,-16);
$ssh->disconnect();
echo $traffic;
I've updated the code above, however, it worked several times , but after deletion of old files, it only creates "traffic.txt" and sometimes it has info in it, sometimes no.
Also, the file "traffic.txtescapeshellarg" is not created anymore. So i was forced to go back to my previous solution and read the "traffic.txt".
So, the solution was very simple. All i needed to do is adding "timeout".
The final code:
$ssh->exec("rm toolkit/traffic/$newfileid");
$ssh->setTimeout(0);
$ssh->exec("mobatch $newsiteid 'lt all;ue print -admitted;' toolkit/traffic");
sleep(8);
$ssh->exec('cat ' . escapeshellarg("toolkit/traffic/$newfileid") . '| grep -A 10 \'$ ue print \' > toolkit/traffic/traffic.txt');
$traffic = $ssh->exec("cat toolkit/traffic/traffic.txt");
$traffic = substr($traffic,21,-83);
echo $traffic;

Ghostscript, Duplex print same side twice when NumCopies is bigger than 1

I using the command :
-q -dBATCH -dNOPAUSE -dNODISPLAY -dPDFFitPage \
-c "mark /BitsPerPixel 1 \
/NoCancel true \
/NumCopies 2 \
/Duplex true \
/OutputFile (%printer%Ricoh c2051) \
/UserSettings << /DocumentName (Arquivo Teste) \
/MaxResolution 500 >> \
(mswinpr2)finddevice putdeviceprops setdevice" -f "C:\Test123.pdf"
The PDF file have 3 pages, when I set the NumCopies 2 for example, the result is 3 pages :
page 1 = the text of page one, in both sides;
page 2 = the text of page two, in both sides;
page 3 = the text of page three, in both sides;
But when I set just one copy the result is 2 pages:
page 1 : the text of page one and in the other side the text of page 2
page 2 : the text of page three and the other side blank .
like Duplex are supposed to be.
Anyone knows how this happened ?
Its a consequence of the way mswinpr2 works, it doesn't care about you setting /Duplex true because the device is not a duplexing device (your printer obviously is, but that's not the same thing). In fact the majority of the command line will have no effect on teh output.
When you set NumCopies, it prints each page 'NumCopies' times to the printer so if your printer is set to do duplexing then it prints the first copy of page 1 on the first side, then the second copy of page 1 on the second side (ie the back of page 1) then the first copy of page 2 on the third side (the front of page 2) and so on.
You cannot achieve multiple collated copies using the mswinpr2 device.
The command line you have set suggests that you have the PostScript option for your printer, you could instead use the ps2write device to convert the PDF to PostScript and send the PostScript to the printer, the latest version of Ghostscript allows for the injection of device-specific options into the output PostScript so you could easily add NumCopies and Duplex there, assuming your printer has sufficient memory to do duplexing and NumCopies at the same time.

ImageMagick generate pdf with special page numbering

I generate a PDF from a set of PNG files using this command:
convert -- $(ls -v -- src/*.png) out/book.pdf
where there're some files with names like -03.png, which I need to have smaller page numbers than others. But I get a PDF which has -01 having page number 1, -02 number 2, etc., and 01 starts from page number 6.
The PDF is a scanned book, which has some elements like table of contents etc. which aren't included in page numbering. I remember to have seen some PDFs which have special page numbers like vii before normal Arabic numbers start.
I've tried using -scene -5 to add an offset to page numbers, but this didn't change the result.
So what should I instead do to make page "01.png" have page number 1, etc., and previous ones have some other numbers (negative or Latin, anything) and appear at the beginning of the document?
First, you want to sort files numerically counting optional minus sign, which you won't do with command you show.
Second, you talk about PageLabels for PDF pages, which you can add using Ghostscript and pdfmark operator.
Try this command:
ls src/*.png | \
sort -n | \
convert #- pdf:- | \
gs \
-sDEVICE=pdfwrite \
-o out/book.pdf \
-c '[{Catalog}<</PageLabels<</Nums[0<</P(-3)>>1<</P(-2)>>2<</P(-1)>>3<</S/D>>]>>>>/PUT pdfmark' \
-f -
It's for 3 pages -3, -2 and -1, followed by any number of pages labelled 1, 2, 3 etc. Modify according to your needs.

Convert subset of postscript file to pdf documents

I have a system that generates large quantities of PostScript files that each contain multiple, multi-page documents. I want to write a script that takes these large PostScript documents and outputs multiple PDF documents from each.
For example one postscript file contains 200 letters to customers, each of which is 10 pages long. This postscript file contains 2000 pages. I want to output from this 1 ps document, 200x 10 page PDFs, one for each customer.
I'm thinking GhostScript is the way to go for this level of document manipulation but I'm not sure the best way to go - Is there a function in GhostScript to take 'pages 1-10' of the input ps file? Do I have to output the entire ps file as 2000 separate ps files (1 per page) then combine them back together again?
Or is there a much simpler way of acheiving my goal with something other than GhostScript?
Many Thanks,
Ben
Technically this will be possible in the next release of Ghostscript, or using the HEAD code in the Git repository. It is now possible to switch devices when using pdfwrite which will cause the device to close and complete the current PDF file. Switching back again will start a new one.
Combine this with a BeginPage and/or EndPage procedure in the page device dictionary, and you should be able to do something like what you want.
Caveat; I haven't tried any of this, and it will take some PostScript programming to get it to work.
Because of the nature of PostScript, there is no way to extract the 'N'th page from a file, so there is no way to specify a range of pages.
As lsemi suggests you could first convert to one large PDF file and then extract the ranges you want. Ghostscript is able to use the FirstPage and LastPage switches to do this (unlike PostScript, it is possible to extract a specific page from a PDF file).
Well, you might first make the PS into a PDF object collection (or directly generate a PDF from GhostScript by printing to the PDFWriter device), and then "cut" from the big PDF using pdftk, which would be quite fast.
Create the complete PDF file first with the help of Ghostscript:
gs \
-o 2000p.pdf \
-sDEVICE=pdfwrite \
-dPDFSETTINGS=/prepress \
2000p.ps
Use pdftk to extract PDF files with 10 pages each:
for i in $(seq 0 10 199); do \
export start=$(( ${i} * 1 + 1 )); \
export end=$(( ${start} + 9 )); \
pdftk \
2000p.pdf \
cat ${start}-${end} \
output pages---${start}..${end}.pdf; \
done
You can have Ghostscript generate a 2000page sample+test PDF for you by first creating a sample PostScript file named '2000p.ps' with these contents:
%!PS
/H1 {/Helvetica findfont 48 scalefont setfont .2 .2 1 setrgbcolor} def
/pageframe {1 0 0 setrgbcolor 2 setlinewidth 10 10 575 822 rectstroke} def
/gopageno {H1 300 700 moveto } def
1 1 2000 {pageframe gopageno
4 string cvs
dup stringwidth pop
-1 mul 0 rmoveto
show
showpage} for
and then run this command:
gs -o 2000p.pdf -sDEVICE=pdfwrite -g5950x8420 2000p.ps