You can't change the name of the output files/the name of the .pdf file **during* the TeX run/LaTeX run.
The reason is:
The output files are created anew and opened for writing right at the beginning of the TeX run/LaTeX run.
(E.g., the .log file is created anew and opened for writing right after starting the tex-executable or latex-executable. E.g., the .pdf file is created anew and opened for writing when shipping out the very first page of the document. )
The output files (and thus also the .pdf file) are left open for writing until the end of the TeX run/LaTeX run.
With most computer platforms you can't change the name of a file while that file is open for writing.
But with most TeX-platforms you can run tex-binaries/executbales with command line options.
One of these options is the option -jobname
.
If you have the main .tex-file foo.tex
and compile it by running latex from the command line as
pdflatex --jobname=bar foo.tex
, you won't get the output files foo.aux
, foo.log
and foo.pdf
, etc, but you will get output files bar.aux
, bar.log
and bar.pdf
, etc.
Also the primitive \jobname
won't deliver the phrase foo
in this case but will deliver the phrase bar
.
You can't use a macro for changing the names of output files during the LaTeX run but you can go the other direction:
Create a macro which examines whether the expansion of \jobname
contains some specific phrase and forks accordingly. Be aware that \jobname
spits out explicit space tokens of category code 10(space) and explicit character tokens of category code 12(other).
Example:
Save the following example as test.tex
:
\documentclass{article}
\usepackage{comment}
\begingroup
\makeatletter
%%----------------------------------------------------------------------
%% Check whether argument is empty:
%%......................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is empty>}%
%% {<Tokens to be delivered in case that argument
%% which is to be checked is not empty>}%
%% The gist of this macro comes from Robert R. Schneck's \ifempty-macro:
%% <https://groups.google.com/forum/#!original/comp.text.tex/kuOEIQIrElc/lUg37FmhA74J>
\long\def\UD@CheckWhetherNull#1{%
\romannumeral0\expandafter\@secondoftwo\string{\expandafter
\@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
\@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
\@secondoftwo\string}\expandafter\expandafter\@firstoftwo{ }{}%
\@secondoftwo}{\expandafter\expandafter\@firstoftwo{ }{}\@firstoftwo}%
}%
%%----------------------------------------------------------------------
%% Check whether expansion of \jobname contains no phase "_sol"
%%......................................................................
%% \UD@CheckWhetherNoSolInJobname{<Tokens to be delivered in case that
%% \jobname contains no phrase "_sol">}%
%% {<Tokens to be delivered in case that
%% \jobname contains the phrsae "_sol">}%
\def\UD@GobbleToSol{_sol}%
\@onelevel@sanitize\UD@GobbleToSol
\edef\CheckWhetherNoSolInJobname{%
\noexpand\expandafter\noexpand\UD@CheckWhetherNull
\noexpand\expandafter{\noexpand\UD@GobbleToSol\jobname\UD@GobbleToSol}%
}%
\expandafter\long\expandafter\def
\expandafter\UD@GobbleToSol\expandafter#\expandafter1\UD@GobbleToSol{}%
\CheckWhetherNoSolInJobname{%
\endgroup
\newcommand\CheckWhetherNoSolInJobname[2]{#1}%
}{%
\endgroup
\newcommand\CheckWhetherNoSolInJobname[2]{#2}%
}%
%% \makeatother not needed. Instead the group is closed.
%%----------------------------------------------------------------------
\CheckWhetherNoSolInJobname{%
\excludecomment{sol}%
}{%
\includecomment{sol}%
}%
\begin{document}
Expansion of \verb|\jobname| is: \texttt{\jobname}
\texttt{\string\jobname} does
\CheckWhetherNoSolInJobname{%
not%
}{%
indeed%
}
contain the phrase \verb|_sol|.
Thus solutions
\CheckWhetherNoSolInJobname{%
are not included%
}{%
get included also%
}.
\bigskip
This is the question.
\begin{sol}
This is the answer.
\end{sol}
\end{document}
Compiling from the command line via pdflatex test.tex
yields test.pdf
which looks like this:

Compiling from the command line via pdflatex --jobname=test_sol test.tex
yields test_sol.pdf
which looks like this:

Another approach could be:
File test_sol.tex
:
\newcommand\solutioninorexclude{%
\includecomment{sol}%
}%
\input test.tex
File test.tex
:
\documentclass{article}
\usepackage{comment}
\providecommand\solutioninorexclude{%
\excludecomment{sol}%
}%
\solutioninorexclude
\begin{document}
This is the question.
\begin{sol}
This is the answer.
\end{sol}
\end{document}
Compiling test_sol.tex
yields test_sol.pdf
:

Compiling test.tex
yields test.pdf
:

A variation on this approach can be having test.tex
create the file test_sol.tex
for you automatically in case it does not exist:
When you save the example below as test.tex
and compile it, you will get a file test.pdf
which contains the text without solutions. You also get a file test_sol.tex
. If you compile that, it will—via \input
—import test.tex
in a way where sol
-environments are included. Thus you get a file test_sol.pdf
which does also contain solutions:
\documentclass{article}
\usepackage{comment}
\providecommand\solutioninorexclude{%
\excludecomment{sol}%
\includecomment{solinputfile}%
}%
\solutioninorexclude
\begin{solinputfile}
\begingroup
\makeatletter
\IfFileExists{\jobname\string_sol.tex}{%
\@latex@warning@no@line{File \jobname\string_sol.tex already exists. Not generating it}%
}{%
\@latex@warning@no@line{Generating file \jobname\string_sol.tex}%
\newwrite\solinputfile
\immediate\openout\solinputfile\jobname\string_sol.tex\relax
\immediate\write\solinputfile{%
\string\newcommand\string\solutioninorexclude{\@percentchar^^J%
\space\space\string\includecomment{sol}\@percentchar^^J%
\space\space\string\excludecomment{solinputfile}\@percentchar^^J%
}\@percentchar^^J%
\string\input\space\jobname.tex%
}%
\immediate\closeout\solinputfile
}%
\endgroup
\end{solinputfile}
\begin{document}
This is the question.
\begin{sol}
This is the answer.
\end{sol}
\end{document}
Yet another approach could be using something like the docstrip package.
The purpose of the docstrip package is copying files of tex-source-code with having comments removed. It provides means for conditional inclusion of code into the copies.
E.g. if you save the following example as test.tex
and compile it, you don't get a .pdf file but you get two new text files.
%<*ignore>
\input docstrip
\nopreamble
\nopostamble
\askforoverwritetrue
\generate{\file{\jobname\string_sol.tex}{\from{\jobname.tex}{sol}}}
\generate{\file{\jobname\string_nosol.tex}{\from{\jobname.tex}{}}}
% Here you can do some \immediate\write18-calls for calling LaTeX or
% TeXify or latexmk for compiling \jobname_sol.tex and
%\jobname_nosol.tex.
% You need to have the \write18-feature enabled for this.
% Some people take enabling \write18 for a security issue.
\csname stop\endcsname
\bye
%</ignore>
\documentclass{article}
% This comment won't occur in the generated files.
% This comment won't occur in the generated files.
\begin{document}
This is the question.
%<*sol>
This is the answer.
%</sol>
\end{document}
One of these text files is named test_nosol.tex
and its content is:
\documentclass{article}
\begin{document}
This is the question.
\end{document}
The other of these text files is named test_sol.tex
and its content is:
\documentclass{article}
\begin{document}
This is the question.
This is the answer.
\end{document}