12

For several years I've used the following in most LaTeX documents to input a macros file that lives in different folders on my Mac and my Linux machine:

\InputIfFileExists{/Mac/path/macros.tex}%
{\input{/Mac/path/macros.tex}}
{\input{/linux/path/macros.tex}}

It worked splendidly until I recently updated my TeX distribution. After updating, I got an error even with this MWE:

\documentclass{amsart}
\InputIfFileExists{/Mac/path/macros.tex}%
{\input{/Mac/path/macros.tex}}
{\input{/linux/path/macros.tex}}
\begin{document}
text
\end{document}

The error reads:

Command \first already defined. Or name \end... illegal, see p. 192 of the manual.

(Here \first is the first command defined in my file macros.tex.)

I see now that changing to \IfFileExists fixes everything, and I'm happy to do that. I'm curious, though, why does \InputIfFileExists throw this error?

A quick Something search for \InputIfFileExists didn't turn up much useful, just this old TeX.SE question.

  • As the name implies, if the file is found it is inputted, and then the second arg is executed inputting the file again, thus error – daleif May 24 '16 at 6:08
  • This presumably never worked, but why not just use \input{macros} the test should not be needed, presumably amsart.cls is in a different location on the two machines but you do not need to refer to the path at all, just the local file name and arrange the search paths are set up correctly in both cases. – David Carlisle May 24 '16 at 8:13
18

TL;DR: You're actually looking for

\IfFileExists{/Mac/path/macros.tex}%
  {\input{/Mac/path/macros.tex}}
  {\input{/linux/path/macros.tex}}

The macro \InputIfFileExists{<file>}{<true>}{<false>} takes three arguments: the file to check the existence of, the <true> code to execute before inputting the file in case it is found and the <false> code to execute if the file doesn't exist. The way you're using it makes me think you're actually looking for \IfFileExists, which is why it works when you switch to that notation.

In your usage

\InputIfFileExists{/Mac/path/macros.tex}%
  {\input{/Mac/path/macros.tex}}
  {\input{/linux/path/macros.tex}}

\InputIfFileExists{<one>}{<two>}{<three>} checks for the existence of <one>. If it exists, it will necessarily execute \input{<one>}. So, if /Mac/path/macros.tex exists, you'll actually end up trying to \input{/Mac/path/macros.tex} twice.

The code \input{/linux/path/macros.tex} will be executed when the file <one> doesn't exist.


If the only reason for conditioning on the path stems from a choice of your operating system, you might be interested in looking at the ifplatform package. See Is there a macro telling which OS we're using?.

  • NTL;R. +1. Nice answer. – Przemysław Scherwentke May 24 '16 at 6:12
  • 2
    All good, except that \InputIfFileExist has three arguments (see clsguide.pdf, section 4.8): \InputIfFileExists{⟨file-name⟩}{⟨true⟩}{⟨false⟩}. It's true that the macro is defined having two, but that's the internal implementation: at the user's level, it should be considered as having three arguments. – egreg May 24 '16 at 7:56
  • +1. Thanks! This clears it up. I still wonder why it compiled without error under TeX Live 2012, though. – Z Norwood May 25 '16 at 4:12
  • 1
    @ZNorwood it would (does) compile without error on linux as then the test is false so the file is only input once, it would always fail if the tested file is there and contains commands like \newcommand that can not be executed twice. – David Carlisle May 25 '16 at 7:02
7

There has been no change to \InputIfFileExists since 1995/05/25 so unless you have not upgraded for a long time the system upgrade is probably unrelated.

However a better, more portable, and more efficient, markup here would be

\documentclass{amsart}
  \input{macros}
\begin{document}
text
\end{document}

or better still rename macros.tex to macros.sty and use

\documentclass{amsart}
  \usepackage{macros}
\begin{document}
text
\end{document}

Just as you do not have to give the full path to amsart.cls and then customise that path on every machine, you should not have to give the full path to locally produced files.

You just need to ensure that macros.tex (or macros.sty) is in the TEXINPUTS path, either by adding the location to the standard path or putting the files into a standard place. So on linux texlive ~/texmf/tex/latex/mymacros/macro.sty would work by default for example (kpsexpand '$TEXMFHOME' will show the value of TEXMFHOME but it defaults to $HOME/texmf)

  • Good suggestion. The reason I use separate paths is just that I like to keep my macros file in my Dropbox, which lives in different places on my different machines. I suppose I could sym-link it to the TeX directory, but, you know, old habits die hard. – Z Norwood May 25 '16 at 4:14
  • 2
    @ZNorwood just put your dropbox directory tree into your TEXINPUTS variable you do not have to move or link anything. – David Carlisle May 25 '16 at 7:00
  • Oh, I see. I didn't read that carefully the first time. – Z Norwood May 26 '16 at 5:51

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.