2

I have n PDFs in a folder. Each PDF contains only one small figure. I want to combine all of these onto one page, one on top of the other. I want to be able to specify just the directory that the PDFs are in and let LaTeX assemble them. It would be even better if I could call this from the command line so I didn't have to open my editor. My situation is like this one (at least the asker's pseudo code is exactly what I had in mind) but I can't understand the answer enough to make it work for combined PDFs.

If it makes it any easier, I could pass in the exact PDF file paths as arguments instead of just the directory. Both approaches are fine with me.

Thanks.

5
  • 1) are you in windows? 2) are you sure that pdfs can fill in one page?
    – touhami
    Jan 22, 2016 at 13:17
  • pdfjam can be really helpful (if you are in Linux or Mac). Take, for example, a look at stackoverflow.com/questions/25451348/…
    – boumol
    Jan 22, 2016 at 14:27
  • I'm on windows. I had seen that other post and tried that method but gave up after I couldn't figure out the error produced by pdfjam (via msys2). I then thought it would be easier to use LaTeX. It seems folks think the pdfjam method so I think I'll just have to figure that out. Thanks for the help. Jan 22, 2016 at 15:36
  • You can also try to use pdfnup pypi.python.org/pypi/pdfnup I suppose that this should work on windows
    – boumol
    Jan 22, 2016 at 15:57
  • please use @name to ping users
    – touhami
    Jan 23, 2016 at 9:04

2 Answers 2

2

A batch solution save this .bat file in the same directory

@echo off 
setlocal EnableDelayedExpansion

(
echo \documentclass{article}
echo \usepackage{graphicx}
echo \begin{document} 
)> combine.tex
for /r %%a in (*.pdf) do (
set mtfile=%%a
set mtfile=!mtfile:%~dp0=!
set mtfile=!mtfile:\=/!
set mtfile="!mtfile:.=".!
echo \includegraphics{!mtfile!}>> combine.tex
echo.>> combine.tex
)
echo \end{document}>> combine.tex

rem could need to renove rem from next line and edit it to point pdflatex directory
rem set path=C:\programm...\miktex\bin;%path%
pdflatex combine.tex

by runing this file you will creat the combine.tex and compile it.

1

Inspired by touhami's brilliantly simple approach, I used the same technique but with Python.

import os, fnmatch, subprocess, getopt, sys

def combinePdfs(inputPdfsDir, outputFileName):
    removeOldCombinedFigure(inputPdfsDir + outputFileName + '.pdf')
    latexText = buildLatexText(inputPdfsDir)
    tempFilePath = inputPdfsDir + outputFileName + '.tex'
    saveTexFile(tempFilePath, latexText)
    callPdfLatex(tempFilePath)
    deleteGenereatedFiles(inputPdfsDir + outputFileName)

def removeOldCombinedFigure(oldCombinedPath):
    try:
        os.remove(oldCombinedPath)
    except OSError:
        pass

def buildLatexText(inputPdfsDir):
    graphics = fnmatch.filter(os.listdir(inputPdfsDir), "*.pdf")
    graphicHeight = 1.0 / len(graphics)
    latexText = """
    \documentclass{article}
    \usepackage{graphicx}
    \usepackage[margin=0.0in]{geometry}
    \\begin{document}
    \\begin{figure}
    \\centering"""
    for g in graphics:
        latexText += "\n\includegraphics[height="
        latexText += str(graphicHeight)
        latexText += "\\textheight,width=\\textwidth,keepaspectratio]{"
        latexText += g
        latexText += "}"
    latexText += "\n\end{figure}"
    latexText += "\n\end{document}"
    return latexText

def saveTexFile(texFilePath, latexText):
    tempFile = file(texFilePath, 'w')
    tempFile.write(latexText)
    tempFile.close()

def callPdfLatex(tempFilePath):
    inputPdfsDir = os.path.dirname(tempFilePath)
    windowsTempFilePath = tempFilePath.replace("/", "\\")
    outDirCommand = "-output-directory=" + inputPdfsDir
    args = ["C:\\Program Files (x86)\\MiKTeX\\miktex\\bin\\pdflatex.exe", outDirCommand, windowsTempFilePath]
    subprocess.call(args, shell = True)

def deleteGenereatedFiles(generatedFileNameNoExt):
    os.remove(generatedFileNameNoExt + '.aux')
    os.remove(generatedFileNameNoExt + '.log')
    os.remove(generatedFileNameNoExt + '.tex')

def usage():
    print('combine_pdfs.py -i C:\\dir_with_pdfs -o combinedPdf')

def main(argv):
    opts, args = getopt.getopt(argv, "h:i:o:")
    inputDir = None
    outputFile = None
    for opt, arg in opts:
        print opt
        if opt in ("-h", "--help"):
            usage()
            sys.exit(2)
        elif opt in ("-i", "--input_dir"):
            inputDir = arg
            if not inputDir.endswith('\\'):
                inputDir += '\\'
        elif opt in ("-o", "--output_file"):
            outputFile = arg
        else:
            usage()
            sys.exit(2)

    combinePdfs(inputDir, outputFile)

if __name__ == "__main__":
    argv = sys.argv[1:]
    main(argv)

Call from the command line like this:

python .\combine_pdfs.py -i C:\Users\yourname\Desktop\dir_with_pdfs -o combined

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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