IPython nbconvert output pdf without In[#] words - jupyter-notebook

When I run below command to convert a IPython notebook to pdf, I wish to remove the leading word "In[#]" but only display the cell content.
ipython nbconvert --to=latex --post=pdf input.ipynb

Some useful information at nbconvert-example.
Just copy style_notebook.tplx to local directory and do some minor modify:
diff --git a/latex_cell_style/use_cell_style.tplx b/latex_cell_style/use_cell_style.tplx
index 72b3c24..9114157 100644
--- a/latex_cell_style/use_cell_style.tplx
+++ b/latex_cell_style/use_cell_style.tplx
## -1,5 +1,5 ##
((= This line selects the cell style. =))
-((* set cell_style = 'style_python.tplx' *))
+((* set cell_style = 'style_notebook.tplx' *))
((= This line inherits from the built in template that you want to use. =))
-((* extends 'latex_article.tplx' *))
\ No newline at end of file
+((* extends 'article.tplx' *))
diff --git a/notebook_cell_style/style_notebook.tplx b/notebook_cell_style/style_notebook.tplx
index 504cd52..7bd9f2a 100644
--- a/notebook_cell_style/style_notebook.tplx
+++ b/notebook_cell_style/style_notebook.tplx
## -1,6 +1,6 ##
((= Notebook input/output style =))
-((* extends 'latex_base.tplx' *))
+((* extends 'base.tplx' *))
% Custom packages
((* block packages *))
## -29,7 +29,7 ##
\newlength{\inputpadding}
\setlength{\inputpadding}{0.5em}
\newlength{\cellleftmargin}
- \setlength{\cellleftmargin}{0.15\linewidth}
+ \setlength{\cellleftmargin}{0\linewidth}
\newlength{\borderthickness}
\setlength{\borderthickness}{0.4pt}
\newlength{\smallerfontscale}
## -177,15 +177,5 ##
% Name: draw_prompt
% Purpose: Renders an output/input prompt for notebook style pdfs
((* macro draw_prompt(prompt, number, color, space) -*))
- \begin{minipage}{\cellleftmargin}%
- \hfill%
- {\smaller%
- \tt%
- \color{(((color)))}%
- (((prompt)))[(((number)))]:}%
- \hspace{\inputpadding}%
- \hspace{(((space)))}%
- \hspace{3pt}%
- \end{minipage}%
((*- endmacro *))
Then copy below files to your notebook directory:
style_notebook.tplx
ipython_nbconvert_config.py
use_cell_style.tplx
Run below command to generate pdf output:
ipython nbconvert test.ipynb
Output as below:

Related

Blogdown fails rendering page as tikzmark library is not found

I am using latest version of blogdown and tinytex to render a page containing this snippet:
The following diagram:
```{r, echo=FALSE, engine='tikz', fig.cap='This is it.', engine.opts = list(template = "../latex/header.tex")}
\begin{tikzpicture}[scale=.7, remember picture]
\tikzmath{ \w = 6; \h =4; \x = 2; \y = 1; }
\draw [fill=gray!30,thick] (-\w/2,-\h/2) rectangle (\w/2,\h/2);
\draw [->,thick] (\w/2,0) -- (\w/2+\x,0);
\draw [->,thick] (-\w/2-\x,0) -- (-\w/2,0);
\node [left] at (-\w/2-\x,0) {Input};
\node [right] at (\w/2+\x,0) {Output};
\node [align=left,font=\ttfamily] at (0,0) {\small function(\subnode {sub}{...}) \{\\\hspace{0.2cm}...\\\}};
\draw[−>,thick] (-\w/2,0) -- (-\w/2 + \w/8,0) -- (-\w/2 + \w/8,\h/4) -- ($ (sub)+(-\w/2.5,\h/5) $) -- ($ (sub)+(0,\h/5) $) -- (sub);
\draw [->,thick] (0,0) -- (\w/2,0);
\end{tikzpicture}
```
Where header.tex is:
\documentclass{article}
\include{preview}
\usepackage[pdftex,active,tightpage]{preview}
\usepackage{amsmath}
\usepackage{tikz}
\usetikzlibrary{matrix}
% OWN CODE START
\usetikzlibrary{math}
\usetikzlibrary{tikzmark}
\usetikzlibrary{calc}
% OWN CODE END
\begin{document}
\begin{preview}
%% TIKZ_CODE %%
\end{preview}
\end{document}
When I run blogdown::build_site(), I get this error:
Quitting from lines 184-195 (mypost.Rmd)
Error: Failed to compile tikz1137adfc9b89.tex. See https://yihui.name/tinytex/r/#debugging for debugging tips. See tikz1137adfc9b89.log for more info.
Execution halted
Error in render_page(f) :
Failed to render 'content/mypost.Rmd'
file tikz1137adfc9b89.tex is (the last lines showing the error):
! Package tikz Error: I did not find the tikz library 'tikzmark'. I looked for
files named tikzlibrarytikzmark.code.tex and pgflibrarytikzmark.code.tex, but n
either could be found in the current texmf trees..
See the tikz package documentation for explanation.
Type H <return> for immediate help.
...
l.9 \usetikzlibrary{tikzmark}
Here is how much of TeX's memory you used:
12142 strings out of 494553
251420 string characters out of 6174236
281626 words of memory out of 5000000
15624 multiletter control sequences out of 15000+600000
3640 words of font info for 14 fonts, out of 8000000 for 9000
14 hyphenation exceptions out of 8191
55i,0n,68p,420b,90s stack positions out of 5000i,500n,10000p,200000b,80000s
! ==> Fatal error occurred, no output PDF file produced!
I am on Mac, on Windows this works :(
Installing the dev version fixes it:
devtools::install_github('yihui/tinytex')

No author details in pdf, from R-Markdown / LaTeX template

I'm trying to create an R-Markdown template based on the BioMed Central LaTeX template (bmc-article.tex).
The bmc template files are available for download here and needless to say, they work just fine: https://www.biomedcentral.com/authors/tex
In particular, the author, address and note definitions work and produce the desired outcome.
I have replaced the example author, adresse and note definitions in the bmc-article.tex file to use that as a tex template. I have also removed most of the example-content in that file.
The definition examples in the bmc-article.tex, I have replaced with:
$for(author)$
\author[%
addressref={$author.addressref$}, %
$if(author.corref)$corref={$author.corref$}, $endif$ %
$if(author.noteref)$noteref={$author.noteref$}, $endif$ %
email={$author.email$} %
]{\inits{$author.inits$}\fnm{$author.fnm$} \snm{$author.snm$}}
$endfor$
$for(address)$
\address[id=$address.id$]{ %
$if(address.orgname)$ \orgname{$address.orgname$}, $endif$ %
$if(address.street)$ \street{$address.street$}, $endif$ %
$if(address.postcode)$ \postcode{$address.postcode$}, $endif$ %
$if(address.city)$ \city{$address.city$}, $endif$ %
$if(address.cny)$ \cny{$address.cny$}$endif$ %
}
$endfor$
\begin{artnotes}
$for(notes)$
\note[id=$notes.id$]{$notes.text$} % note, connected to author
$endfor$
\end{artnotes}
When 'knitr'ing the Rmd file, it is (as far as I can tell), converted into meningful tex, and I have perused the resulting tex file again and again looking for tex-errors, but find none.
E.g.:
author:
- fnm: "Soren"
snm: "ONeill"
inits: "S"
addressref: "aff1"
email: "sorens mail"
corref: "aff1"
noteref: "n1"
..becomes:
\author[%
addressref={aff1}, %
corref={aff1}, %
noteref={n1}, %
email={sorens mail} %
]{\inits{S}\fnm{Soren} \snm{ONeill}}
The resulting pdf file however is not correct. The superscript numbers which associate names with addresses is displayed as questionmarks and author details at the end of the article is missing altogether.
I fail to see any significant difference between the tex file created by pandoc (based on my Rmd file) and the original bmx template tex file.
The following is rather lengthy I know.
The Rmd example file
title: "Template testing"
author:
- fnm: "Soren"
snm: "ONeill"
inits: "S"
addressref: "aff1"
email: "sorens mail"
corref: "aff1"
noteref: "n1"
- fnm: "Lotte"
snm: "ONeill"
inits: "L"
addressref: "aff2"
email: "lottes mail"
address:
- id: "aff1"
orgname: "University of Southern Denmark"
street: "Campusvej 55"
postcode: "DK 5500"
city: "Odense M"
cny: "Denmark"
- id: "aff2"
orgname: "University of Southern Denmark"
street: "Campusvej 55"
postcode: "DK 5500"
city: "Odense M"
cny: "Denmark"
notes:
- id: "n1"
text: "Equal contributor"
date: "2 jun 2017"
output:
pdf_document:
template: template.tex
keep_tex: TRUE
---
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see rmarkdown.rstudio.com.
This is the template.tex file, which I have adapted from the downloaded bmc-article.tex file
%% BioMed_Central_Tex_Template_v1.06
\documentclass{bmcart}
\usepackage[utf8]{inputenc} %unicode support
\def\includegraphic{}
\def\includegraphics{}
\begin{document}
\begin{frontmatter}
\begin{fmbox}
\dochead{Research}
\title{$title$}
$for(author)$
\author[%
addressref={$author.addressref$}, %
$if(author.corref)$corref={$author.corref$}, $endif$ %
$if(author.noteref)$noteref={$author.noteref$}, $endif$ %
email={$author.email$} %
]{\inits{$author.inits$}\fnm{$author.fnm$} \snm{$author.snm$}}
$endfor$
$for(address)$
\address[id=$address.id$]{ %
$if(address.orgname)$ \orgname{$address.orgname$}, $endif$ %
$if(address.street)$ \street{$address.street$}, $endif$ %
$if(address.postcode)$ \postcode{$address.postcode$}, $endif$ %
$if(address.city)$ \city{$address.city$}, $endif$ %
$if(address.cny)$ \cny{$address.cny$}$endif$ %
}
$endfor$
\begin{artnotes}
$for(notes)$
\note[id=$notes.id$]{$notes.text$} % note, connected to author
$endfor$
\end{artnotes}
\end{fmbox}% comment this for two column layout
\begin{abstractbox}
\begin{abstract} % abstract
\parttitle{First part title} %if any
Text for this section.
\parttitle{Second part title} %if any
Text for this section.
\end{abstract}
\begin{keyword}
\kwd{sample}
\kwd{article}
\kwd{author}
\end{keyword}
\end{abstractbox}
\end{frontmatter}
%$body$
\begin{backmatter}
\section*{Competing interests}
The authors declare that they have no competing interests.
\section*{Author's contributions}
Text for this section \ldots
\section*{Acknowledgements}
Text for this section \ldots
\bibliographystyle{bmc-mathphys} % Style BST file (bmc-mathphys, vancouver, spbasic).
\bibliography{bmc_article} % Bibliography file (usually '*.bib' )
\end{backmatter}
\end{document}
This produces the following tex file (I've instructed RStudio/pandoc to retain the tex file):
%% BioMed_Central_Tex_Template_v1.06
\documentclass{bmcart}
\usepackage[utf8]{inputenc} %unicode support
\def\includegraphic{}
\def\includegraphics{}
\begin{document}
\begin{frontmatter}
\begin{fmbox}
\dochead{Research}
\title{Template testing}
\author[%
addressref={aff1}, %
corref={aff1}, %
noteref={n1}, %
email={sorens mail} %
]{\inits{S}\fnm{Soren} \snm{ONeill}}
\author[%
addressref={aff2}, %
%
%
email={lottes mail} %
]{\inits{L}\fnm{Lotte} \snm{ONeill}}
\address[id=aff1]{ %
\orgname{University of Southern Denmark}, %
\street{Campusvej 55}, %
\postcode{DK 5500}, %
\city{Odense M}, %
\cny{Denmark} %
}
\address[id=aff2]{ %
\orgname{University of Southern Denmark}, %
\street{Campusvej 55}, %
\postcode{DK 5500}, %
\city{Odense M}, %
\cny{Denmark} %
}
\begin{artnotes}
\note[id=n1]{Equal contributor} % note, connected to author
\end{artnotes}
\end{fmbox}% comment this for two column layout
\begin{abstractbox}
\begin{abstract} % abstract
\parttitle{First part title} %if any
Text for this section.
\parttitle{Second part title} %if any
Text for this section.
\end{abstract}
\begin{keyword}
\kwd{sample}
\kwd{article}
\kwd{author}
\end{keyword}
\end{abstractbox}
\end{frontmatter}
%\subsection{R Markdown}\label{r-markdown}
This is an R Markdown document. Markdown is a simple formatting syntax
for authoring HTML, PDF, and MS Word documents. For more details on
using R Markdown see rmarkdown.rstudio.com.
\begin{backmatter}
\section*{Competing interests}
The authors declare that they have no competing interests.
\section*{Author's contributions}
Text for this section \ldots
\section*{Acknowledgements}
Text for this section \ldots
\bibliographystyle{bmc-mathphys} % Style BST file (bmc-mathphys, vancouver, spbasic).
\bibliography{bmc_article} % Bibliography file (usually '*.bib' )
\end{backmatter}
\end{document}
The latex log file is rather lengthy (lots of stuff about Unicode char's etc), but this is possibly helpful
LaTeX Warning: Reference `aff1thanks' on page 1 undefined on input line 19.
LaTeX Font Info: Try loading font information for OMS+cmss on input line 19.
LaTeX Font Info: No file OMScmss.fd. on input line 19.
LaTeX Font Warning: Font shape `OMS/cmss/m/n' undefined
(Font) using `OMS/cmsy/m/n' instead
(Font) for symbol `textdagger' on input line 19.
LaTeX Warning: Reference `aff2thanks' on page 1 undefined on input line 25.
\address#aff1=\toks21
\address#aff2=\toks22
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <7> on input line 46.
LaTeX Font Info: External font `cmex10' loaded for size
(Font) <5> on input line 46.
LaTeX Warning: Reference `aff1thanks' on page 1 undefined on input line 46.
No file template_test_1.bbl.
AED: lastpage setting LastPage
LaTeX Font Warning: Font shape `OT1/cmss/m/it' in size <8> not available
(Font) Font shape `OT1/cmss/m/sl' tried instead on input line 89.
Overfull \hbox (1.0pt too wide) has occurred while \output is active
[]
[]
[1{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}
] (./template_test_1.aux)
LaTeX Font Warning: Size substitutions with differences
(Font) up to 1.0pt have occurred.
LaTeX Font Warning: Some font shapes were not available, defaults substituted.
LaTeX Warning: There were undefined references.
Of course, I have noticed the warning about "Reference `aff2thanks'", but find no such reference in the original bmx-article.tex
Again, I know this is long -- I apologize for that. I hope someone can make suggestions...

QT5.8. custom Virtual keyboard including

I'm writing a custom virtual keyboard, which based on QtVirtualKeyboard. For my project I would need to be able to use my version of keyboard.
But the only method, which i found is recompile project and replace original "qtvirtualkeyboardplugin.dll" in "mingw53_32\plugins\platforminputcontexts" on my version of "qtvirtualkeyboardplugin.dll". And use the qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard")); function in main.cpp
After hours of reading the docs and trying various things I'm still cannot find method to use custom keyboard localy, without deleting original "qtvirtualkeyboardplugin.dll".
I'm assuming that you've forked the code, in which case the following modifications seem to be enough to get a differently named plugin to be installed to plugins/platforminputcontexts:
Rename qtvirtualkeyboard/src/virtualkeyboard/qtvirtualkeyboard.json to qtvirtualkeyboard/src/virtualkeyboard/customvirtualkeyboard.json.
In customvirtualkeyboard.json, rename the qtvirtualkeyboard key to customvirtualkeyboard.
In qtvirtualkeyboard/src/virtualkeyboard/plugin.cpp, change the contents of the pluginName string to customvirtualkeyboard.
In qtvirtualkeyboard/src/virtualkeyboard/plugin.h, change the FILE string to customvirtualkeyboard.
In src/virtualkeyboard/virtualkeyboard.pro, change TARGET = qtvirtualkeyboardplugin to TARGET = customvirtualkeyboardplugin. This affects the name of the installed .dll, .lib, etc. that you see in plugins/platforminputcontexts.
Here are the changes as a Git diff:
diff --git a/src/virtualkeyboard/customvirtualkeyboard.json b/src/virtualkeyboard/customvirtualkeyboard.json
new file mode 100644
index 0000000..9ef7a87
--- /dev/null
+++ b/src/virtualkeyboard/customvirtualkeyboard.json
## -0,0 +1,3 ##
+{
+ "Keys": [ "customvirtualkeyboard" ]
+}
diff --git a/src/virtualkeyboard/plugin.cpp b/src/virtualkeyboard/plugin.cpp
index 73ddeab..4abe9a4 100644
--- a/src/virtualkeyboard/plugin.cpp
+++ b/src/virtualkeyboard/plugin.cpp
## -76,7 +76,7 ## using namespace QtVirtualKeyboard;
Q_LOGGING_CATEGORY(qlcVirtualKeyboard, "qt.virtualkeyboard")
-static const char pluginName[] = "qtvirtualkeyboard";
+static const char pluginName[] = "customvirtualkeyboard";
static const char inputMethodEnvVarName[] = "QT_IM_MODULE";
static const char pluginUri[] = "QtQuick.VirtualKeyboard";
static const char pluginSettingsUri[] = "QtQuick.VirtualKeyboard.Settings";
diff --git a/src/virtualkeyboard/plugin.h b/src/virtualkeyboard/plugin.h
index 08074d1..19593a4 100644
--- a/src/virtualkeyboard/plugin.h
+++ b/src/virtualkeyboard/plugin.h
## -38,7 +38,7 ##
class QVirtualKeyboardPlugin : public QPlatformInputContextPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID QPlatformInputContextFactoryInterface_iid FILE "qtvirtualkeyboard.json")
+ Q_PLUGIN_METADATA(IID QPlatformInputContextFactoryInterface_iid FILE "customvirtualkeyboard.json")
public:
QStringList keys() const;
diff --git a/src/virtualkeyboard/qtvirtualkeyboard.json b/src/virtualkeyboard/qtvirtualkeyboard.json
deleted file mode 100644
index 76d1706..0000000
--- a/src/virtualkeyboard/qtvirtualkeyboard.json
+++ /dev/null
## -1,3 +0,0 ##
-{
- "Keys": [ "qtvirtualkeyboard" ]
-}
diff --git a/src/virtualkeyboard/virtualkeyboard.pro b/src/virtualkeyboard/virtualkeyboard.pro
index 4f3ca69..e9b0ff9 100644
--- a/src/virtualkeyboard/virtualkeyboard.pro
+++ b/src/virtualkeyboard/virtualkeyboard.pro
## -1,4 +1,4 ##
-TARGET = qtvirtualkeyboardplugin
+TARGET = customvirtualkeyboardplugin
DATAPATH = $$[QT_INSTALL_DATA]/qtvirtualkeyboard
QMAKE_DOCS = $$PWD/doc/qtvirtualkeyboard.qdocconf
Remember that if you're using an open source license, you have to make modifications to Qt code available to users of your application.

Show changes/diffs without a parent commit (first commit) with JGit

when I do a git show commit of the first commit in a repository, I see all the files along with the diffs of the files (i.e all the lines being added)
$ git show cb5d132
commit cb5d13286cf9d14782f0e10445456dfe41072f55
Author: tw2 tw2LastName <tw2>
Date: Thu Oct 23 05:15:09 2014 -0400
Initial Commit
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..96d156e
--- /dev/null
+++ b/README.txt
## -0,0 +1 ##
+First Line in README file!
\ No newline at end of file
The jgit show doesn't seem to get similar info, How can I get similar output using JGit API? I could use DiffFormatter, but it seems to require the baseTree and commitTree, wondering how I can get the DiffFormatter to work on the first commit in the repository.
ByteArrayOutputStream os = new ByteArrayOutputStream();
DiffFormatter df = new DiffFormatter( os )
RawTextComparator cmp = RawTextComparator.DEFAULT;
df.setRepository(repository);
df.setDiffComparator(cmp);
df.setDetectRenames(true);
// wondering how to use the API if we do not have baseCommit.
List<DiffEntry> diffEntries = df.scan(??baseCommitTree??, firstCommit.getTree());
for (DiffEntry diffEntry : diffEntries) {
df.format(diffEntry);
}
System.out.println(df.toString());
Use an o.e.jgit.treewalk.EmptyTreeIterator to compare the first commit against:
AbstractTreeIterator oldTreeIter = new EmptyTreeIterator();
ObjectReader reader = repository.newObjectReader();
AbstractTreeIterator newTreeIter = new CanonicalTreeParser(null, reader, firstCommit.getTree());
List<DiffEntry> diffEntries = df.scan(oldTreeIter, newTreeIter);
...

How can I merge PDF files (or PS if not possible) such that every file will begin in a odd page?

I am working on a UNIX system and I'd like to merge thousands of PDF files into one file in order to print it. I don't know how many pages they are in advance.
I'd like to print it double sided, such that two files will not be on the same page.
Therefore it I'd the merging file to be aligned such that every file will begin in odd page and a blank page will be added if the next place to write is an even page.
Here's the solution I use (it's based on #Dingo's basic principle, but uses an easier approach for the PDF manipulation):
Create PDF file with a single blank page
First, create a PDF file with a single blank page somewhere (in my case, it is located at /path/to/blank.pdf). This command should work (from this thread):
touch blank.ps && ps2pdf blank.ps blank.pdf
Run Bash script
Then, from the directory that contains all my PDF files, I run a little script that appends the blank.pdf file to each PDF file with an odd page number:
#!/bin/bash
for f in *.pdf; do
let npages=$(pdfinfo "$f"|grep 'Pages:'|awk '{print $2}')
let modulo="($npages %2)"
if [ $modulo -eq 1 ]; then
pdftk "$f" "/path/to/blank.pdf" output "aligned_$f"
# or
# pdfunite "$f" "/path/to/blank.pdf" "aligned_$f"
else
cp "$f" "aligned_$f"
fi
done
Combine the results
Now, all aligned_-prefixed files have even page numbers, and I can join them using
pdftk aligned_*.pdf output result.pdf
# or
pdfunite aligned_*.pdf result.pdf
Tool info:
ps2pdf is in the ghostscript package in most Linux distros
pdfinfo, pdfunite are from the Poppler PDF rendering library (usually the package name is poppler-utils or poppler_utils)
pdftk is usually its own package, the pdftk package
your problem can be more easily solved if you look at this from an another point of view
to obtain that, in printing, page 1 of second pdf file will be not attached to last page of first pdf file on the same sheet of paper, and, more generally, first page of subsequent pdf file will be not printed on the back of the same sheet with the last page of the precedent pdf file
you need to perform a selective addition of one blank page only to pdf files having and odd number of pages
I wrote a simple script named abbblankifneeded that you can put in a file and then copy in /usr/bin or /usr/local/bin
and then invoke in folder where you have your pdf with this syntax
for f in *.pdf; do addblankifneeded $f; done
this script adds a blank page at end to pdf files having an odd number of pages, skipping pdf files having already an even number of pages and then join together all pdf into one
requirements: pdftk, pdfinfo
NOTE: depending from your bash environment, you may need to replace sh interpreter with bash interpreter in the first line of script
#!/bin/sh
#script to add automatically blank page at the end of a pdf documents, if count of their pages is a not a module of 2 and then to join all pdfs into one
#
# made by Dingo
#
# dokupuppylinux.co.cc
#
#http://pastebin.com/u/dingodog (my pastebin toolbox for pdf scripts)
#
filename=$1
altxlarg="`pdfinfo -box $filename| grep MediaBox | cut -d : -f2 | awk '{print $3 FS $4}'`"
echo "%PDF-1.4
%µí®û
3 0 obj
<<
/Length 0
>>
stream
endstream
endobj
4 0 obj
<<
/ProcSet [/PDF ]
/ExtGState <<
/GS1 1 0 R
>>
>>
endobj
5 0 obj
<<
/Type /Halftone
/HalftoneType 1
/HalftoneName (Default)
/Frequency 60
/Angle 45
/SpotFunction /Round
>>
endobj
1 0 obj
<<
/Type /ExtGState
/SA false
/OP false
/HT /Default
>>
endobj
2 0 obj
<<
/Type /Page
/Parent 7 0 R
/Resources 4 0 R
/Contents 3 0 R
>>
endobj
7 0 obj
<<
/Type /Pages
/Kids [2 0 R ]
/Count 1
/MediaBox [0 0 595 841]
>>
endobj
6 0 obj
<<
/Type /Catalog
/Pages 7 0 R
>>
endobj
8 0 obj
<<
/CreationDate (D:20110915222508)
/Producer (libgnomeprint Ver: 2.12.1)
>>
endobj
xref
0 9
0000000000 65535 f
0000000278 00000 n
0000000357 00000 n
0000000017 00000 n
0000000072 00000 n
0000000146 00000 n
0000000535 00000 n
0000000445 00000 n
0000000590 00000 n
trailer
<<
/Size 9
/Root 6 0 R
/Info 8 0 R
>>
startxref
688
%%EOF" | sed -e "s/595 841/$altxlarg/g">blank.pdf
pdftk blank.pdf output fixed.pdf
mv fixed.pdf blank.pdf
pages="`pdftk $filename dump_data | grep NumberOfPages | cut -d : -f2`"
if [ $(( $pages % 2 )) -eq 0 ]
then echo "$filename has already a multiple of 2 pages ($pages ). Script will be skipped for this file" >>report.txt
else
pdftk A=$filename B=blank.pdf cat A B output blankadded.pdf
mv blankadded.pdf $filename
pdffiles=`ls *.pdf | grep -v -e blank.pdf -e joinedtogether.pdf| xargs -n 1`; pdftk $pdffiles cat output joinedtogether.pdf
fi
exit 0
You can use PDFsam:
gratis
runs on Microsoft Windows, Mac OS X and Linux
portable version available (at least on Windows)
can add a blank page after each merged document if the document has an odd number of pages
Disclaimer: I'm the author of the tools I'm mentioning here.
sejda-console
It's a free and open source command line interface for performing pdf manipulations such as merge or split. The merge command has an option stating:
[--addBlanks] : add a blank page after each merged document if the number of pages is odd (optional)
Since you just need to print the pdf I'm assuming you don't care about the order your documents are merged. This is the command you can use:
sejda-console merge -d /path/to/pdfs_to_merge -o /outputpath/merged_file.pdf --addBlanks
It can be downloaded from the official website sejda.org.
sejda.com
This is a web application backed by Sejda and has the same functionalities mentioned above but through a web interface. You are required to upload your files so, depending on the size of your input set, it might not be the right solution for you.
If you select the merge command and upload your pdf documents you will have to flag the checkbox Add blank page if odd page number to get the desired behaviour.
Here is a PowerShell version of the most popular solution using pdftk. I did this for windows but you can use PowerShell Core for other platforms.
# install pdftk server if on windows
# https://www.pdflabs.com/tools/pdftk-server/
$blank_pdf_path = ".\blank.pdf"
$input_folder = ".\input\"
$aligned_folder = ".\aligned\"
$final_output_path = ".\result.pdf"
foreach($file in (Get-ChildItem $input_folder -Filter *.pdf))
{
# easy but might break if pdfinfo output changes
# takes 7th line with the "Page: 2" and matches only numbers
(pdfinfo $file.FullName)[7] -match "(\d+)" | Out-Null
$npages = $Matches[1]
$modulo = $npages % 2
if($modulo -eq 1)
{
$output_path = Join-Path $aligned_folder $file.Name
pdftk $file.FullName $blank_pdf_path output $output_path
}
else
{
Copy-Item $file.FullName -Destination $aligned_folder
}
}
$aligned_pdfs = Join-Path $aligned_folder "*.pdf"
pdftk $aligned_pdfs output $final_output_path
Preparation
Install Python and make sure you have the pyPDF package.
Create a PDF file with a single blank in /path/to/blank.pdf (I've created blank pdf pages here).
Save this as pdfmerge.py in any directory of your $PATH. (I'm not a Windows user. This is straight forward under Linux. Please let me know if you get errors / if it works.)
Make pdfmerge.py executable
Every time you need it
Run uniprint.py a directory that contains only PDF files you want to merge.
pdfmerge.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from argparse import ArgumentParser
from glob import glob
from pyPdf import PdfFileReader, PdfFileWriter
def merge(path, blank_filename, output_filename):
blank = PdfFileReader(file(blank_filename, "rb"))
output = PdfFileWriter()
for pdffile in glob('*.pdf'):
if pdffile == output_filename:
continue
print("Parse '%s'" % pdffile)
document = PdfFileReader(open(pdffile, 'rb'))
for i in range(document.getNumPages()):
output.addPage(document.getPage(i))
if document.getNumPages() % 2 == 1:
output.addPage(blank.getPage(0))
print("Add blank page to '%s' (had %i pages)" % (pdffile, document.getNumPages()))
print("Start writing '%s'" % output_filename)
output_stream = file(output_filename, "wb")
output.write(output_stream)
output_stream.close()
if __name__ == "__main__":
parser = ArgumentParser()
# Add more options if you like
parser.add_argument("-o", "--output", dest="output_filename", default="merged.pdf",
help="write merged PDF to FILE", metavar="FILE")
parser.add_argument("-b", "--blank", dest="blank_filename", default="blank.pdf",
help="path to blank PDF file", metavar="FILE")
parser.add_argument("-p", "--path", dest="path", default=".",
help="path of source PDF files")
args = parser.parse_args()
merge(args.path, args.blank_filename, args.output_filename)
Testing
Please make a comment if this works on Windows and Mac.
Please always leave a comment if it doesn't work / it could be improved.
It works on Linux. Joining 3 PDFs to a single 200-page PDF took less then a second.
Martin had a good start. I updated to PyPdf2 and made a few tweaks like sorting the output by filename.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from argparse import ArgumentParser
from glob import glob
from PyPDF2 import PdfFileReader, PdfFileWriter
import os.path
def merge(pdfpath, blank_filename, output_filename):
with open(blank_filename, "rb") as f:
blank = PdfFileReader(f)
output = PdfFileWriter()
filelist = sorted(glob(os.path.join(pdfpath,'*.pdf')))
for pdffile in filelist:
if pdffile == output_filename:
continue
print("Parse '%s'" % pdffile)
document = PdfFileReader(open(pdffile, 'rb'))
for i in range(document.getNumPages()):
output.addPage(document.getPage(i))
if document.getNumPages() % 2 == 1:
output.addPage(blank.getPage(0))
print("Add blank page to '%s' (had %i pages)" % (pdffile, document.getNumPages()))
print("Start writing '%s'" % output_filename)
with open(output_filename, "wb") as output_stream:
output.write(output_stream)
if __name__ == "__main__":
parser = ArgumentParser()
# Add more options if you like
parser.add_argument("-o", "--output", dest="output_filename", default="merged.pdf",
help="write merged PDF to FILE", metavar="FILE")
parser.add_argument("-b", "--blank", dest="blank_filename", default="blank.pdf",
help="path to blank PDF file", metavar="FILE")
parser.add_argument("-p", "--path", dest="path", default=".",
help="path of source PDF files")
args = parser.parse_args()
merge(args.path, args.blank_filename, args.output_filename)
`
The code by #Chris Lercher in https://stackoverflow.com/a/12761103/1369181 did not quite work for me. I do not know whether that is because I am working on Cygwin/mintty. Also, I have to use qpdf instead of pdftk. Here is the code that has worked for me:
#!/bin/bash
for f in *.pdf; do
npages=$(pdfinfo "$f"|grep 'Pages:'|sed 's/[^0-9]*//g')
modulo=$(($npages %2))
if [ $modulo -eq 1 ]; then
qpdf --empty --pages "$f" "path/to/blank.pdf" -- "aligned_$f"
else
cp "$f" "aligned_$f"
fi
done
Now, all "aligned_" files have even page numbers, and I can join them using qpdf (thanks to https://stackoverflow.com/a/51080927):
qpdf --verbose --empty --pages aligned_* -- all.pdf
And here the useful code from https://unix.stackexchange.com/a/272878 that I have used for creating the blank page:
echo "" | ps2pdf -sPAPERSIZE=a4 - blank.pdf
This one worked for me. Have used pdfcpu on macos.
Can be installed this way:
brew install pdfcpu
And have slightly adjusted the code from https://stackoverflow.com/a/12761103/1369181
#!/bin/bash
mkdir aligned
for f in *.pdf; do
let npages=$(pdfcpu info "$f"|grep 'Page count:'|awk '{print $3}')
let modulo="($npages %2)"
if [ $modulo -eq 1 ]; then
pdfcpu page insert -pages l -mode after "$f" "aligned/$f"
else
cp "$f" "aligned/$f"
fi
done
pdfcpu merge merged-aligned.pdf aligned/*.pdf
rm -rf aligned
NB! It creates and removes "aligned" directory in the current directory. So feel free to improve it to make it safe for use.

Resources