# Check for empty macro argument

There is a description on how to check whether the argument of a macro is empty in What does \ifx\\#1\\ stand for?

Unfortunately, I can't get any of the examples there to work.

Among others, I have used the following code:

\documentclass{article}
\def\test#1.#2\\{%
\ifx\\#2\\
<no extension #2 is empty, because \\=\\>
\else
<extension is #2>
\fi%
}
\begin{document}
\test myfile.tex
\test myfile
\end{document}


What is wrong with my code? What is the problem with my usage of the snippets?

-
\test myfile does not match the macro definition because it must include a dot and \\. –  Christian Lindig Jan 4 '13 at 20:44

There is no \\ delimiter in the code you're using, so the first argument can be found, but not the second and the file ends during the search for \\.

In other words, with your definition of \test the first argument ends with the first period (at brace level 0), the second at the first appearance of \\ which isn't there.

Moreover, in the second call there is no period, so the first argument can't be found.

You have to do it more cautiously; something like this:

\def\test#1{\xtest#1.\\}

\def\xtest#1.#2\\{%
\ifx\\#2\\%
\typeout{<no extension>}%
\else
\typeout{<extension is \removedot#2\\>}
\fi}

\def\removedot#1.\\{#1}


and call it as

\test{file.tex}
\test{file}


Let's see the various cases:

\test{file.tex}


becomes

\xtest file.tex.\\


which results in assigning

#1 = file, #2 = tex.


The final dot will be removed by \removedot.

The call

\test{file}


will become

\xtest file.\\


resulting in

#1 = file, #2 = <empty>


as desired.

A perhaps easier parsing can be obtained with the help of xparse:

\usepackage{xparse}
\NewDocumentCommand{\test}{>{\SplitArgument{1}{.}}m}{\xtest #1}
\NewDocumentCommand{\xtest}{mm}
{%
\IfNoValueTF{#2}
{\typeout{No extension}}
{\typeout{Extension is #2}}%
}


This spares from the \removedot postprocessing.

-

LaTeX includes a filename parser:

\documentclass{article}
\makeatletter
\def\test#1{%
\filename@parse{#1}%
\ifx\filename@ext\relax
#1 has no extension%
\else
the extension of #1 is \filename@ext
\fi}

\makeatother

\begin{document}
\test{myfile.tex}

\test{myfile}
\end{document}

-
\documentclass{article}
\usepackage{libertine}
\makeatletter
\def\test#1{\expandafter\test@i#1..\@nil}
\def\test@i#1.#2.#3\@nil{%
\ifx\relax#2\relax
<no extension #2 is empty, because \string\relax=\string\relax>
\else
<extension is #2>
\fi}
\makeatletter
\begin{document}
\test{myfile.tex}
\test{myfile}

\def\TEST{myfile.sty}
\test{\TEST}
\end{document}


if you do not want to put the argument into braces (what should be the preferred way) you can use something like

\def\test#1/{\expandafter\test@i#1..\@nil}
...

\test foo.bar/
\test foo/

-