将多个txt合并为一个

将多个txt合并为一个

有很多.txt文件,我试图在 Latex 中找出一种方法将所有文件合并*.txt为一个*.txt。我想过和\newread\newwrite但我不知道是否有更好的方法或如何开始。它们*.tex具有相同的结构,它们都用于spreadtab,但在使用之前spreadtab,我想过将它们合并。我的第一个想法是使用\input,但它并不像我想象的那么容易。

答案1

此答案未涵盖合并不同输入编码的文本文件的问题。
下文假设所有源文件都具有相同的输入编码,并且目标文件的输入编码应与源文件的输入编码相同。

作为弗兰已经说过了,你不用 TeX 就可以做到这一点,只需使用 shell 命令即可:

在 Linux 终端上
cat MYfileA.tex MYfileB.tex MYfileC.tex > MYfilesABCmerged.tex
应该可以解决问题。

在 Windows PowerShell(其中cat是 cmdlet 的别名Get-Content)中,这也可能起到作用。

在 Windows PowerShell 中,另一种变体可能是:
Get-Content MYfileA.tex,MYfileB.tex,MYfileC.tex | Out-File MYfilesABCmerged.tex

然而,请注意Windows PowerShellOut-File默认情况下,以 UTF-8 格式(重新)编码它生成的文件,没有字节顺序标记,并且您需要使用参数-Encoding以不同的编码进行(重新)编码。

在 Windows 命令提示符下
type MYfileA.tex MYfileB.tex MYfileC.tex > MYfilesABCmerged.tex

copy MYfileA.tex + MYfileB.tex + MYfileC.tex MYfilesABCmerged.tex
应该可以解决问题。

在任何情况下,例如,当使用通配符*/时?,请确保目标文件不在要合并的源文件集中!

如果你坚持使用 LaTeX 来做,你可能可以做如下的事情:

% Create three text files
% =======================
\begin{filecontents*}{MYfileA.tex}
01 file A
02 file A
03 file A
04 file A
05 file A
06 file A
07 file A
08 file A
09 file A
10 file A
\end{filecontents*}
\begin{filecontents*}{MYfileB.tex}
01 file B
02 file B
03 file B
04 file B
05 file B
06 file B
07 file B
08 file B
09 file B
10 file B
\end{filecontents*}
\begin{filecontents*}{MYfileC.tex}
01 file C
02 file C
03 file C
04 file C
05 file C
06 file C
07 file C
08 file C
09 file C
10 file C
\end{filecontents*}


% Code for macro for merging files
% ================================
\makeatletter
\newread\ThisInFile
\newwrite\ThisOutFile
\newcommand\mergefiles[2]{%
%\NewDocumentCommand\mergefiles{vv}{%
  \begingroup
  \let\do\@makeother
  \dospecials        %    verbatim-category-code-régime.
  \do\^^I
  \do\^^M
  \endlinechar=-1\relax
  \newlinechar=-1\relax
  \IfFileExists{#2}{%
    \@latex@warning@no@line{%
       File `\detokenize{#2}' already exists on the system.%
       \MessageBreak Not generating it from this source%
    }%
  }{%
    \immediate\openout\ThisOutFile #2
    %\immediate\openout\ThisOutFile \string"#2\string"
    %\immediate\openout\ThisOutFile "#2"
    \@for\ThisInFileName:={#1}\do{%
      \expandafter\IfFileExists\expandafter{\ThisInFileName}{%
        \immediate\openin\ThisInFile \ThisInFileName\relax
        %\immediate\openin\ThisInFile \string"\ThisInFileName\string"\relax
        %\immediate\openin\ThisInFile "\ThisInFileName"\relax
        \appendthisfileloop
        \immediate\closein\ThisInFile
      }{%
        \@latex@warning@no@line{%
           File `\detokenize\expandafter{\ThisInFileName}' not found on the system.%
           \MessageBreak Therefore it cannot be included into the merge%
        }%
      }%
    }%
    \immediate\closeout\ThisOutFile
  }%
  \endgroup
}%
\newcommand\appendthisfileloop{%
  \ifeof\ThisInFile\else
    \immediate\read\ThisInFile to \thisline
    \ifx\thisline\empty\ifeof\ThisInFile\expandafter\expandafter\expandafter\@gobble\fi\fi
    {%
      \immediate\write\ThisOutFile{\detokenize\expandafter{\thisline}}%
      %\message{(\detokenize\expandafter{\thisline})}%
    }%
  \expandafter\appendthisfileloop\fi
}%
\makeatother


% Let's merge the three text files:
% =================================
\mergefiles{MYfileA.tex,MYfileB.tex,MYfileC.tex}{MYfilesABCmerged.tex}%


% Have a document which uses the verbatim-package 
% for displaying the file where things are merged:
% ================================================
\documentclass{article}

%\usepackage{xparse}
\usepackage{verbatim}

\begin{document}

\noindent This is the content of file \verb|MYfilesABCmerged.tex|:

\verbatiminput{MYfilesABCmerged.tex}

\end{document}

在此处输入图片描述

陷阱/警告

!!!通过上面示例的代码,确保使用宏时\mergefiles目标文件不会出现在源文件的逗号列表中!!!
(如果源文件之一也是目标文件,则意味着在创建目标文件的过程中,在将其读取为源文件之前会破坏该文件。)
使用宏时,\mergefiles不会对此实施错误检查。即,\mergefiles不会检查目标文件是否也出现在源文件的逗号列表中!

使用 TeX/LaTeX 复制文本文件时需要注意的事项:

  • 根据文件名中可能出现的字符,您可能希望使用 LaTeX 格式\mergefiles来定义\NewDocumentCommand类型参数v(=verbatim)。
    对于较旧的 LaTeX 发行版,您可能需要加载包解析为此。
    “取决于可能出现的字符”:在此,我想到不匹配的字符,如{或,}因为在通常的宏参数/非逐字类型参数中,这些字符只有在匹配的对应项也存在时才会出现。对于 DOS/Windows 中的文件路径,反斜杠用于分隔嵌套目录/文件夹的名称,我想到\在 TeX 中会引入控制序列标记。我想到不应该扩展/执行的活动字符。... 虽然类别代码为 6(参数),但#TeX/LaTeX 文件名中出现的哈希通常不是问题 - 除非尝试定义临时宏,这些宏会扩展到不基于\edef\unexpanded/的文件名⟨token-注册⟩

  • 使用 TeX 程序进行操作时,目标文件中总会存在松散的空格字符序列,而源文件中的空格字符序列出现在输入文本文件行的右端。对此您无能为力,因为 TeX 在预处理输入文本文件行的阶段就已经丢弃了这些空格,甚至在查看用于标记事物的类别代码之前。

  • 使用 TeX 程序时,目标文件中的换行符(CR 或 CR+LF 之类的东西)的编码可能与源文件中的换行符编码不同。这是因为文件是逐行处理的,当将一行文本写入目标文件时,换行符标记由 TeX 的写入例程生成。据我所知,现在使用 TeX 发行版(如 TeX Live 或 MiKTeX),您可以在写入文件时指定换行符的编码。更多信息可以在TeX Live 指南—2021/ 在里面MiKTeX 手册修订版 4.2

  • 当使用 TeX 程序进行操作时,在目标文件中你可能会得到^^某些字符的符号 -TeXBook,附录 C:字符代码说:

    关于字符代码的约定很少被硬编码到 TeX 中:
    [...]
    (6) 有一个以十六进制形式表示字符 0–255 的特殊约定^^00-^^ff^,在第 8 章中解释。当是 catcode 7 的任何字符时,此约定始终可以作为输入接受。按照此约定生成文本输出仅有的当表示 TeX 安装程序选择不直接输出的代码 ≥ 128 的字符时。

    ^^例如,在 TeX Live 和 MiKTeX 中,您可以提供文件扩展名为 .tcx 的翻译文件,以指定当 TeX 将它们写入外部文本文件时要用 -notation 表示哪些字符。

    但我认为,有了最新的 TeX 发行版,您就不需要太担心这个问题了:

    例如,TeX Live 指南—2021在章节中说9.1.2 2004

    • 几乎所有格式都允许大多数字符通过“翻译文件”以原样打印cp227.tcx,而不是用符号翻译它们^^。具体来说,位置 32–256 的字符,加上制表符、垂直制表符和换页符被视为可打印且不翻译。例外是纯 TeX(仅 32–126 可打印)、ConTeXt(0–255 可打印)和 Ω 相关格式。此默认行为与 TeX Live 2003 中的行为几乎相同,但实现得更清晰,具有更多自定义可能性。请参阅 texmf-dist/doc/web2c/web2c.html#TCX-文件(顺便说一下,使用 Unicode 输入,TeX 在显示错误上下文时可能会输出部分字符序列,因为它是面向字节的。)

    例如,2000 年 12 月,如今已过时的MiKTeX 手册修订版 2.0在章节中说5.7 TCX 文件:字符翻译

    默认情况下,不会翻译任何字符,并且 32 到 126(含)之间的字符代码(十进制)是可打印的。无法使这些(或任何)字符不可打印。

    (我没有在当前版本中找到有关“字符翻译”默认设置的任何声明MiKTeX 手册修订版 4.2。也许我只是忽略了这些。如果是这样,我很高兴得到提示,这样我就可以编辑这个答案。)


关于文件名/目录路径:

当在要由 TeX 程序处理的代码中指定文件名时(例如,在 LaTeX 文档中或 LaTeX 包的 .sty 文件中等等),您需要处理特定于正在使用的平台/shell/操作系统/文件系统的特殊性。

  • 例如,需要读取要合并的文件的权限,还需要创建/写入具有合并内容的目标文件的权限。
  • "例如,在 MiKTeX 和 TeX Live 中,如果文件名/文件路径包含空格字符,则需要/可以将其嵌套在引号 ( ) 中,这使得指定包含引号的文件名/文件路径变得困难。
  • 例如,FAT16 等文件系统不允许文件名/目录路径中出现空格,而 NTFS 或 Ext3/Ext4 等文件系统则允许。
  • 例如,用于基于 Web2C 的 TeX 实现的路径搜索的 Kapathsea 库将包含字符串的文件名或文件路径$&视为尝试使用 shell 变量——这使得指定包含字符串的文件名变得困难$&
  • 例如,通常/\通过使用操作系统/shell,在路径规范中将文件夹名称/目录名称彼此分开。
  • 例如,在 Windows 中:,路径规范的某些地方并不作为文件夹/目录/文件名称的一部分,而是作为终止文件系统/数据卷/驱动器规范的内容。
  • 例如在许多操作系统中*可以?用作通配符。

因此,除了在文件名中使用空格字符所带来的问题之外,还有例如字符"$, ,&/\:,在文件名/文件路径中的使用可能会出现问题,这是由于所使用的平台/shell/操作系统所施加的限制,尽管所使用的文件系统的规范可能不限制这些字符的使用*?

这可能会使某些平台/shell/操作系统难以访问文件系统中的某些文件,尽管可以通过其他平台/shell/操作系统访问它们。

相关内容