I thought a good use of part of my Sunday would be to (re?)learn a little Perl and make my life a bit easier. Suppose you have a paper that’s split up into many files. This script will parse your main LaTeX file and generate a single LaTeX file for the whole paper. It searches recursively for “\input{}” commands and replaces them with the relevant file. It seems to be functional enough to use, but everyone has their own LaTeX usage conventions, so YMMV.
This is particularly handy for submitting papers to ArXiV, which requires a single .tex file, and cutting and pasting in 20 little files can become a bit of a pain. With the perl script for stripping comments, you can generate the .tex for your ArXiV submission on the fly.
I spent a little time searching for a script like this online, since I’m sure many people have written such a thing, but I didn’t turn anything up. Hopefully this will be of use to others looking for a similar hack. Sorry for the lines getting chopped off in the display — it should show up if you cut and paste the text.
#!/usr/bin/perl # mergetex.pl # # Script for merging tex files into a single monolithic file. This # script should make it easy to generate an ArXiV-friendly single # .tex file from a paper that is broken into subfiles using LaTeX's # \input{} command. # # USAGE: # ./mergetex.pl [input] [output] # ./mergetex.pl mypaper.tex mypaperMerged.tex # # mergetex takes two arguments, the [input] file and the [output] # file into which the merged files should go. It recursively # searches [input] and adds any file given by uncommented \input{} # commands. # # v0.1 by Anand Sarwate (asarwate@alum.mit.edu) with tips from Erin Rhode. use IO::File; if ( scalar(@ARGV) != 2) { die "Syntax Error : use 'mergetex.pl [input] [output]'" } $infile = shift; $outfile = shift; print "Generating tex file from $infile and storing in $outfile.\n"; my $outputfh = new IO::File($outfile, "w") or die "Could not open $outfile: $!\n"; my $inputfh = new IO::File($infile, "r") or die "Could not open $infile: $!\n"; parsetex($inputfh,$infile); $outputfh->close(); sub parsetex { my $fh = shift; my $file = shift; print "Found $file. Merging into $outfile.\n"; while () { # strip out comments $decom = $_; $decom =~ s/^\%.*$/\%/; $decom =~ s/([^\\])\%.*$/\1\%/g; # search for lines with "\input{}" if ($decom =~ /\\input{(.*?)}/) { #get new file name if ($1 =~ /.tex/) { my $newfile = $1; } else { $newfile = $1 . ".tex"; } # recurse to input new file my $newfh = new IO::File($newfile, "r") or die "Could not open $infile: $!\n"; parsetex($newfh,$newfile); } else { $outputfh->print($decom); } } $fh->close(); }
An acknowledgment!
I love how in perl there’s always eight different ways to do the same thing… the whole my $outputfh = new IO::File($outfile, “w”) syntax is is new to me. I always just use open (OUTPUTFH, “>$outfile”). (But that’s because I hate declaring my variables unless absolutely necessary.)
I did that so that I could pass the file handle to the subroutine. I guess I didn’t need it for the output file…
Hi Arnand,
I think the cut and past has failed to show a couple of commands: is there a missing because it thinks it is an HTML tag?
Great that you put this up!
Neil
It seems to work fine for me — what is not working?
Hey Anand,
Amazing that I found this script while Googling :-). I had an issue with the script as well. Where it says “while () {“, I think it should read ” while () {“. It’s possible your blogging system stripped this out. Maybe posting the file itself would be easier than making people copy-paste? Or, given advances in technology since you wrote this post :-), you could use a Github gist:
https://gist.github.com/
Awesome! I will post an update then when I get back on Monday. Thanks a bunch!
Yikes; the blogging system stripped my response too! Following my own advice, the modified script is here:
https://gist.github.com/2175026
Pingback: Updated perl script for merging TeX files for ArXiV « An Ergodic Walk
Pingback: mergetex script updated | An Ergodic Walk