I want to create two pdf output files of a single LaTeX source.

One output file is public and the other one (with further information) becomes private.

I use a make file, which uses find to grep the tex file in the directory. This is a simple solution because this way I can reuse the makefile for many projects without needing to modify its content.

This is the important part of the makefile.

        # This creates the public output file
        find -name *.tex -exec sh -c 'pdflatex {}' \;

Now I want to add a further line to create the private output file. It should look something like this:

        # This creates the public output file
        find -name *.tex -exec sh -c 'pdflatex {}' \;
        # This creates the private output file
        find -name *.tex -exec sh -c 'pdflatex --jobname=ABC  '\def\privatflag{}\input{XYZ}' {}' \;

For ABC I look for a solution to specify the default filname but with a prefix.

For XYZ I look for a solution to pass the input filename here.

The usage of the inner quotation marks is also not correct here I think.

Update 1: Maybe I can explain the problem more simple way.

This command works in the command shell:

pdflatex --jobname=outputfile '\def\privatflag{}\input{inputfile.tex}'

But I'm looking for a solution to use it with find -name *.tex -exec so that I don't need to specify the intput filename inputfile.tex.

Additionally I look for a way that I don't need to specify --jobname=outputfile. It should match the input filename with an additional prefix.

Update 2: Thanks to muru and Stéphane Chazelas, the issue is solved.

This is now the important part of the makefile

        # This creates the public output file
        find -name *.tex -exec sh -c 'pdflatex {}' \;
        # This creates the private output file
        find . -name '*.tex' -execdir sh -c 'pdflatex --jobname=privat_"$${1##*/}" "\def\privatflag{""}\input{$${1##*/}}"' {}-job {} \;
  • Did you mean the other becomes private? Also, why sh -c ...? Why not just -exec pdflatex {} and -exec pdflatex --jobname=ABC '\def\privatflag{}\input{XYZ}' {}? If you ran these commands manually, how would it look, to get an idea of what ABC and XYZ are. – muru Dec 20 '15 at 12:00
  • The sh -c is not required here, but when I keep it away, it does not help me further solving the issue. – Neverland Dec 20 '15 at 14:20
  • 2
    Maybe it doesn't help. But there's no reason to complicate things when you're trying to troubleshoot an issue. – muru Dec 20 '15 at 14:21
  • Yes. This is true. – Neverland Dec 20 '15 at 14:25
  • How would the pdflatex command be affected by directories? For example, what would you do for some/path/some/input.tex? – muru Dec 20 '15 at 14:39

From your example, I think what you need is:

find . -name '*.tex' -execdir sh -c 'pdflatex --jobname=foo"${1##*/}" "\def\privatflag{""}\input{${1##*/}}"' {}-job {} \;

To break it down:

  • -execdir runs the command in the directory where the file was found.
  • ${1##*/} strips the path from the argument given by find.
  • The "" in {} is to prevent find from replacing {} with the matched path.

sh -c is need to process the path given by find and extract just the filename.

| improve this answer | |
  • Your solution is perfect! It is exactly what I was looking for. Thanks a lot! – Neverland Dec 20 '15 at 18:48
  • Update: The solution works fine on command and in a shell script, but inside a Makefile, the "${1##*/}" part is just ignored. When using it in a Makefile, the output filename is just foo.pdf – Neverland Dec 20 '15 at 19:35
  • 1
    Note that that {}-job won't work with all find implementations (some will pass that {}-job literally (unexpanded)). – Stéphane Chazelas Dec 20 '15 at 19:56
  • 2
    @Neverland, Makefiles have their own variables. You need to write a $ as $$ if you want it passed to the shell. – Stéphane Chazelas Dec 20 '15 at 19:58
  • @ Stéphane Chazelas: Thanks a lot! This caused the error. – Neverland Dec 20 '15 at 20:00

Since you are already using a Makefile, you could replace your find by make's own mechanisms to handle files, assuming the simple case that your .tex files are in the current directory. For example, this makefile might suffice:

ALLTEX = $(wildcard *.tex)
ALLPDF = $(ALLTEX:.tex=.pdf) $(ALLTEX:.tex=.internal.pdf)

%.pdf: %.tex
        pdflatex $<
%.internal.pdf: %.tex
        pdflatex --jobname=$@ '\def\privatflag{}\input{$<}'

all: $(ALLPDF)

The variable ALLTEX holds the names of all the input files, and ALLPDF converts these names by replacing the suffix .tex by .pdf and again by another suffix so you have twice the number of wanted output files.

The next 2 lines setup a rule saying how to generate a pdf file from a tex file, and the following 2 lines setup another rule for how to generate the other suffix. $< will be replaced by the input file, and $@ by the output filename.

Finally, the real target all: says it depends on the wanted pdf files. Using make rules has the advantage that a pdf will not be rebuilt if the source tex file has not changed.

| improve this answer | |
  • I wonder if OP wants recursion. – muru Dec 20 '15 at 17:58
  • @muru I agree your answer is much simpler and especially so if the .tex files are not in the immediate directory. I just wanted to explore other solutions for fun. – meuh Dec 20 '15 at 18:03
  • ah, no, I'm not sure my answer is simpler. I think make can be recursive, but I haven't used it much, so I don't know how. And I am too lazy to look it up at the moment. But given the features that make provides, just running find is... ugly. – muru Dec 20 '15 at 18:06

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.