# Expandable version of \InputIfFileExists or \IfFileExists

From this question: Cannot use \toprule when doing \input inside tabular -- why? I know that everything inside the tabular environment should better be expandable. The MWE below suggests that \InputIfFileExists is not, although the error message is different now:

! Missing \endcsname inserted.
\def
l.8       \end{tabular}


File main.tex:

\documentclass{standalone}
\usepackage{booktabs}

\begin{document}
\begin{tabular}{ll}
\InputIfFileExists{inp.tex}{}{}
\end{tabular}
\end{document}


File inp.tex:

\toprule
a & b \\
c & d \\
\bottomrule


How do I check, in an expandable fashion, if a file exists and input it if it does?

The following question is related: Why is \input not expandable?

-

The check if a file exists is not expandable, because the file is opened using \openin\somefilehandle=<filename> which makes an assignment to \somefilehandle. Then \ifeof\somefilehandle is used to check if the end-of-file (EOF) is already reached, which is immediately true for non-existing files. Empty files, I think, need to be read at least once before EOF is reached. Assignments are not expandable, therefore the test isn't. However, reading a whole file using TeX's \input (renamed to \@@input by LaTeX, while \input is redefined to an unexpandable form) does not require the assignment of an filehandle and therefore is expandable.

You could however, check if the file exists outside the tabular and have an fully expandable macro which includes the content if the file exists or does nothing else.

\documentclass{standalone}
\usepackage{booktabs}

\newif\ifmyfileexists
\makeatletter
\let\originput\@@input
\makeatother

\begin{document}
\IfFileExists{inp}{\myfileexiststrue}{\myfileexistsfalse}%
\begin{tabular}{ll}
\ifmyfileexists
\originput inp
\fi
\end{tabular}
\end{document}


Or using some user level macros:

\documentclass{standalone}
\usepackage{booktabs}

\makeatletter
\newcommand{\testfileexists}[1]{%
\IfFileExists{#1}%
{\def\inputtestedfile{\@@input #1 }}
{\let\inputtestedfile\@empty}%
}
\makeatother

\begin{document}
\testfileexists{inp}
\begin{tabular}{ll}
\inputtestedfile
\end{tabular}
\end{document}

-

This is my first LuaTeX code, so please bear with me. :)

For completeness sake, I'll add a LuaTeX solution, as Joseph mentioned in the comments. I believe the Lua code is self-explanatory.

Let's suppose I have a file meow.tex with the following content:

Hello cat!


And the file mydoc.tex :

\documentclass{article}

\usepackage{luacode}

\begin{luacode}
-- Checks if file exists.
function checkFile(theFile)

-- open a file handler
local fileHandler = io.open(theFile,"r")

-- check if the handler is valid
if fileHandler then

-- the file exists, close
fileHandler:close()

-- print the input command
tex.print("\\input{" .. theFile .. "}")

end
end
\end{luacode}

\begin{document}

Hello world!

\myinput{meow.tex}

\end{document}


Running lualatex mydoc.tex, the following output is obtained:

Replacing meow.tex by woof.tex (which doesn't exist), we get the following output:

There we go, a nice fallback. :) We could even add an else branch in the Lua code to print a message about the missing file.

-
Mmm, I need a better file checking code in my standalone package for the automated build feature. Using Lua code like this might be the way (if LuaTeX is used of course). Do you now a way to get the full absolute path of the file or the full relative path from the current directory? –  Martin Scharrer Apr 28 '12 at 8:24
@MartinScharrer: I tried to find a way to get the full absolute path of the file, but it was quite complicated. The only solution I could find is a third-party pure Lua library named Penlight built on top of the LuaFileSystem which happens to have an abspath function to get the absolute path of a file. To get the full path of the current directory, you could use require 'lfs' and lfs.currentdir(). –  Paulo Cereda Apr 28 '12 at 10:51
Dear downvoter, care to explain why my answer deserves your criticism? :) –  Paulo Cereda Mar 3 '13 at 10:09

No, this is not possible as not all of the the underlying primitive used for the file check are expandable. In particular, the file check uses \openin, which is not expandable, although the actual test for end-of-file (\ifeof) is expandable.

You can use the \input primitive (stored by LaTeX2e as \@@input), which is expandable, but this cannot check for file existence. So this is only safe if the file is definitely available.

-
Note that a LuaTeX solution will be expandable as \directlua is, but I'm not sufficiently up on Lua to know the appropriate functions to use. –  Joseph Wright Apr 5 '12 at 9:03