# How can I check if the filename of a LaTeX document contains a string?

I am preparing a LaTeX beamer presentation for students. I am looking for a simple way to create two versions of my presentation.

One version for the Students, which just contains the text of the tasks they get for homework and an other one for me which also contains the solution.

So I have created a macro that is intended to check if the file name contains "student". If it does, the macro outputs nothing, and if it does not, the argument is passed:

\newcommand{\hausaufgabenLoesung}[1]{%
\IfSubStringInString{student}{\jobname}{}{#1}%
}


But this does not work as intended. No matter how I name the file, the conditional always goes to the false-expression. I think the \jobname macro returns something which can not be processed by \IfSubStringInString but I have no other idea how I could approach this.

If I replace the \jobname macro in the conditional with a fixed string, it works as intended but this would render it fairly useless.

I used \jobname to avoid including the currfile-package, but with the currfile-macros I get the same behaviour. I am using texlive 2014 pdflatex on Linux and Windows.

Anyone here got a hint for that?

Here is a minimal complete example:

\documentclass[ngerman]{beamer}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}

\usepackage{ifthen}
\usepackage{substr}

\newcommand{\hausaufgabenLoesung}[1]{%
\IfSubStringInString{student}{\jobname}{}{#1}%
}

\begin{document}

\begin{frame}{Title}{Subtitle}
\begin{itemize}
\item \jobname
\item Visible in both files
\hausaufgabenLoesung{\item Solution not in the student file}
\end{itemize}
\end{frame}

\end{document}

• Welcome to TeX.SX! A tip: You can use backticks  to mark your inline code. – mvkorpel Aug 21 '14 at 12:26
• Perhaps you should try \IfSubStr from xstring package. And you mean \usepackage[ngerman]{babel}, not vice versa ;-) – user31729 Aug 21 '14 at 12:32
• Thanks! But I get the same behaviour with the changed macro: \newcommand{\hausaufgabenLoesung}[1]{\IfSubStr{\jobname}{student}{}{#1}} – Andi Aug 21 '14 at 12:37
• Perhaps tex.stackexchange.com/questions/101479/… may solve the problem you care about - but not with the method you're trying. – Ethan Bolker Aug 21 '14 at 12:47
• The chars in \jobname all have \catcode 12. See tex.stackexchange.com/questions/6828/…. – Ulrike Fischer Aug 21 '14 at 13:12

The characters in \jobname have category code 12 and this defies substr, which uses an \ifx based comparison. You can simply stringify student, using the fact that substr commands fully expand their arguments:

\documentclass[ngerman]{beamer}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}

\usepackage{substr}

\newcommand{\hausaufgabenLoesung}[1]{%
\IfSubStringInString{\detokenize{student}}{\jobname}{}{#1}%
}

\begin{document}

\begin{frame}{Title}{Subtitle}
\begin{itemize}
\item \jobname
\item Visible in both files
\hausaufgabenLoesung{\item Solution not in the student file}
\end{itemize}
\end{frame}

\end{document}


This is what I get if the file name doesn't contain student:

This is what I get if the file name contains student:

A classical solution (without \detokenize):

\documentclass[ngerman]{beamer}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}

\usepackage{substr}

\begingroup\escapechar=-1
\xdef\studentstring{\string\student}
\endgroup

\newcommand{\hausaufgabenLoesung}[1]{%
\IfSubStringInString{\studentstring}}{\jobname}{}{#1}%
}

\begin{document}

\begin{frame}{Title}{Subtitle}
\begin{itemize}
\item \jobname
\item Visible in both files
\hausaufgabenLoesung{\item Solution not in the student file}
\end{itemize}
\end{frame}

\end{document}


A solution with regular expressions (vastly generalizable):

\documentclass[ngerman]{beamer}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}

\usepackage{xparse,l3regex}

\ExplSyntaxOn
\NewDocumentCommand{\hausaufgabenLoesung}{m}
{
\regex_match:nVF {student} \c_job_name_tl {#1}
}
\cs_generate_variant:Nn \regex_match:nnF { nV }
\ExplSyntaxOff

\begin{document}

\begin{frame}{Title}{Subtitle}
\begin{itemize}
\item \jobname
\item Visible in both files
\hausaufgabenLoesung{\item Solution not in the student file}
\end{itemize}
\end{frame}

\end{document}

• Thanks! \IfSubStringInString{\detokenize{student}}{\jobname}{}{#1} did the trick to me! After Ulrikes comment I have already heard from \detokenize but I tried to use it on \jobname instead of my string. Guess I have to read about that again. Thank you! – Andi Aug 22 '14 at 5:23
• Because I find it to be more elegant, I created an environment for the same purpose. I use the comment-Package for the ability to hide the environment. The environ-Package seems to be incompatible with lstlisting. \IfSubStr{\jobname}{\detokenize{student}}{\excludecomment{hausaufgabenLoesung}}{\newenvironment{hausaufgabenLoesung}{}{}} – Andi Aug 22 '14 at 6:10
• As of September 2015, \c_job_name_tl should become \c_sys_jobname_str – egreg Sep 30 '15 at 9:49
• Thanks for the hint! Do you have a source for that? I am interested in the reason for the change. – Andi Sep 30 '15 at 17:08
• @Andi The team restructured some code, adding some modules, among which sys for "runtime" things. After an update to expl3 I always look for the changes. – egreg Sep 30 '15 at 17:23

According to Ulrike Fischer's comment \jobname consists of 'wrong' catcode characters, a direct comparison is not possible with some hacks. One workaround is to write the jobname to a dummy file and read it immediately back to some \def\.... macro, say \RealJobName. This can be used as one string placeholder for the tests.

The \AtBeginDocument{} environment hook automatically does this and 'returns' the jobname in \RealJobName for later use.

Both approaches with substr and xstring work.

## studentname.tex

\documentclass[ngerman]{beamer}

\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[ngerman]{babel}%

\usepackage{ifthen}
\usepackage{substr}
\usepackage{xstring}%

\newcommand{\hausaufgabenLoesung}[1]{%
\IfSubStringInString{student}{\RealJobName}{}{#1}%
}

\newcommand{\hausaufgabenLoesungXString}[1]{%
\IfSubStr{\RealJobName}{student}{}{#1}%
}

\gdef\RealJobName{}%

\newwrite\mywrite%
\AtBeginDocument{%
\immediate\openout\mywrite\jobname.dum%
\immediate\write\mywrite{\jobname}%
\immediate\closeout\mywrite%
}%

\begin{document}

\begin{frame}{Title}{Subtitle}
\begin{itemize}
\item \jobname
\item Visible in both files
\hausaufgabenLoesung{\item Solution not in the student file}
\hausaufgabenLoesungXString{\item Solution not in the student file}
\end{itemize}
\end{frame}

\end{document}
`