16

I have an external text file that contains a list of names of TeX input files. The names have trailing extensions .tex. For example, the external text file named data.txt contains the following list:

a.tex
b.tex
c.tex

There is a PDF file for each TeX input file in the same directory in which data.txt exists.

The following codes are expected to iterate the file name without extension and import the corresponding PDF.

\documentclass{article}
\usepackage{graphicx}

\begin{document}
\newread\reader
\immediate\openin\reader=data.txt\relax
\loop
    \read\reader to \x
    \unless\ifeof\reader
        \includegraphics{\x}\par
\repeat
\immediate\closein\reader
\end{document}

Could you help me to implement the trimming macro to remove .tex in \x?

2
  • Off-topic suggestion: Throw the list into Excel and use =SUBSTITUTE(A1;".tex";""). Add .tex whenever required by TeX.
    – percusse
    Commented Dec 30, 2011 at 11:54
  • 2
    I'm not sure if it helps, but the xstring package has \StrBefore. Using \StrBefore{hello.tex}{.tex} gives me hello. Commented Dec 30, 2011 at 12:04

3 Answers 3

21
+50

The LaTeX2e kernel, provides some commands for parsing paths and extensions. It is preferable to use them for this type of parsing.

The macro \filename@parse scans its argument and splits it into three parts which are then saved in the macros \filename@area, \filename@base, \filename@ext

\documentclass{article}
\begin{document}
\makeatletter
\filename@parse{path/name.tex}
\filename@area, \filename@base, \filename@ext
\makeatother
\end{document}

In your case \filename@base will represent the trimmed filename, with no path or extension information.

7
  • Fascinating! Is there a handy reference (perhaps even a cheat-sheet) for such commands?
    – qubyte
    Commented Dec 30, 2011 at 13:07
  • 2
    @MarkS.Everitt: Yes, macros2e. Commented Dec 30, 2011 at 13:15
  • AFAIK, this won't work correctly with path/name.with.dots.tex, because everything after the first, not last, dot is taken as the extension. Commented Dec 30, 2011 at 13:17
  • @MartinScharrer One shouldn't name files this way; but under normal circumstances this would work. What you interested is the extension and in your example the extension is with.dots.tex, which you want removed. If you save a file under latex as test.sty.tex and you input{test} LaTeX will import it with no issue.
    – yannisl
    Commented Dec 30, 2011 at 13:21
  • @YiannisLazarides: No, \input{test} will try test and then test.tex, but will not find test.sty.tex. How should it be able to know if it is not test.abc.tex, test.xyz.tex, etc. etc.; I agree that files should not be named like that, but as say, package programmer you need to think about supporting them. Commented Dec 30, 2011 at 13:25
8

As already stated by Yiannis Lazarides the internal LaTeX2e \filename@parse macro can be used to parse the file name. However, the code for splitting the extension off assumes that there is only one dot in the filename and that everything after it is the file extension. Therefore you will get incorrect results for filename with multiple dots as shown below.

I recently added support for multi-dot filenames to my currfile package (shows the current file name, path, extension, etc.), by reimplementing parts of the \filename@parse internals. Unfortunately there is no public interface, but you could use it as follows:

\documentclass{article}
\usepackage{currfile}[2011/09/18]
\begin{document}
\makeatletter
\filename@parse{path/name.tex}
\filename@area, \filename@base, \filename@ext

% Will take 'width.dots.tex' as the extension
\filename@parse{path/name.with.dots.tex}
\filename@area, \filename@base, \filename@ext

% Works with internal 'currfile' redefinitions:
{
\let\filename@simple\currfile@parseext
\let\filename@base\@gobble
\filename@parse{path/name.with.dots.tex}
\filename@area, \filename@base, \filename@ext
}

\makeatother
\end{document}
4

Here is a possible definition, in which also options for every graphic file can be stated

\documentclass{article}
\usepackage{graphicx}

\makeatletter
\newread\inclfromfile@read
\newcommand\includefromfile[2][]{%
  \openin\inclfromfile@read#2\relax
  \loop\read\inclfromfile@read to \@tempa
    \unless\ifeof\inclfromfile@read
    \filename@parse{\@tempa}%
    \begingroup\edef\x{\endgroup
      \noexpand\includegraphics[#1]{\filename@base}\noexpand\par}\x
  \repeat
  \closein\inclfromfile@read
}
\makeatother


\begin{document}
\begin{center}
\includefromfile[scale=1.2]{data.txt}
\end{center}
\end{document}

Notice that \immediate does nothing before \openin and \closein (it's different from \openout and \closeout, where in the absence of \immediate the commands would execute during the next \shipout operation that involves them).

It's important to say \noexpand\par as in some environments (notably center), \par is redefined as a macro.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .