编译为与源文件名称不同的 PDF 文件

编译为与源文件名称不同的 PDF 文件

我有一个包含一些问题及其解决方案的乳胶文档。我还有一个宏\excludecomment{sol},如果取消注释,则会排除解决方案环境。(对于环境也有类似的命令prob。)

一般问题是我是否可以在这些宏中包含一个命令,或者以其他方式,以便根据宏是否处于活动状态来反映在 PDF 文件的文件名中(例如,在存在解决方案时在文件名中添加 _sol。)

答案1

您无法更改输出文件的名称/.pdf 文件的名称期间TeX 运行/LaTeX 运行。

原因是:

输出文件在 TeX 运行/LaTeX 运行开始时重新创建并打开以供写入。
(例如,在启动 tex 可执行文件或 latex 可执行文件后立即重新创建并打开以供写入。例如,在发送文档的第一页时重新创建并打开 .pdf 文件以供写入。)
输出文件(以及 .pdf 文件)保持打开以供写入,直到 TeX 运行/LaTeX 运行结束。
在大多数计算机平台上,您无法在文件打开以供写入时更改文件的名称。

但是在大多数 TeX 平台中,您可以使用命令行选项运行 tex 二进制文件/可执行文件。

其中一个选项是选项-jobname

如果你有主 .tex 文件foo.tex并通过从命令行运行 latex 来编译它,如下所示

pdflatex --jobname=bar foo.tex

,您将不会获得输出文件foo.auxfoo.logfoo.pdf等,但您将获得输出文件bar.auxbar.logbar.pdf等。

同样,在这种情况下,原始人\jobname不会传递短语foo,但会传递短语bar

您不能在 LaTeX 运行期间使用宏来更改输出文件的名称,但您可以反其道而行之:

创建一个宏,检查的扩展是否\jobname包含某些特定短语并相应地分叉。请注意,\jobname会吐出类别代码 10(空格)的显式空格标记和类别代码 12(其他)的显式字符标记。


例子:

将以下示例保存为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}

通过命令行进行编译,pdflatex test.tex结果test.pdf如下:

在此处输入图片描述

通过命令行进行编译,pdflatex --jobname=test_sol test.tex结果test_sol.pdf如下:

在此处输入图片描述



另一种方法可能是:

文件test_sol.tex

\newcommand\solutioninorexclude{%
  \includecomment{sol}%
}%
\input test.tex

文件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}

编译test_sol.tex结果test_sol.pdf

在此处输入图片描述

编译test.tex结果test.pdf

在此处输入图片描述

此方法的另一种变体是,如果文件不存在,则自动为您test.tex创建该文件:test_sol.tex

当您将下面的示例另存为test.tex并编译它时,您将获得一个test.pdf包含文本但不包含解决方案的文件。您还会获得一个文件test_sol.tex。如果您编译它,它将通过\input—importtest.tex以包含环境的方式进行。因此,您将获得一个也包含解决方案的sol文件:test_sol.pdf

\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}


另一种方法可能是使用类似文档条 包。目的是文档条 软件包正在复制 tex-source-code 文件并删除注释。它提供了将代码有条件地包含到副本中的方法。

例如,如果您将以下示例保存为test.tex并进行编译,那么您不会获得 .pdf 文件,但会获得两个新的文本文件。

%<*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}

其中一个文本文件被命名test_nosol.tex,其内容为:

\documentclass{article}
\begin{document}
This is the question.
\end{document}

其中另一个文本文件的名称test_sol.tex及其内容为:

\documentclass{article}
\begin{document}
This is the question.

This is the answer.
\end{document}

答案2

我也遇到过同样的情况多年今天浏览 TeX.stackexchange 后,我找到了以下解决方案。它并没有严格回答您的问题,但我发现它很容易用作解决方法。我使用包,exam但这应该适用于任何可以选择使用宏注释掉某些部分的包。对于exam包,可选包含的代码在环境中solution。我创建了三个文件,其方案如下(但实际上名称更短):

1)main_questions_only.tex,其全部内容为

\documentclass[11pt]{exam}
\noprintanswers
\input{main.tex}

2)main_questions_with_solutions.tex,其全部内容为

\documentclass[11pt]{exam}
\printanswers
\input{main.tex}

3)main.tex 包含其他所有内容。

答案3

本质上这个问题是TeX 可以对其生成的 PDF 进行后期处理吗?

LuaTeX 有一个回调可以用于此。

%! TEX program = lualatex
\documentclass{article}
\usepackage{luacode}
\begin{document}

123

\begin{luacode*}
luatexbase.add_to_callback("wrapup_run", function()
    local outfile=io.open(tex.jobname.."_sol.pdf", "wb")
    outfile:write(io.open(tex.jobname..".pdf", "rb"):read("a"))
    outfile:close()
    os.remove(tex.jobname..".pdf")
end, "final callback to rename pdf file")
\end{luacode*}

\end{document}

请注意,文档(texdoc luatex)指出......

需要您自担风险使用它。

因此,如果您使用此解决方案,请准备好调试新编译器版本中可能出现的任何问题。

相关内容