将大量文本文件合并为一个大文本文件

将大量文本文件合并为一个大文本文件

我想将数千个小文本文件合并为一个大文本文件。我将它们放在结构如下的目录中:timestamp1/status.txt。例如:20130430133144/status.txt。到目前为止,我知道

cat */* > bigtextfile.txt

适用于少量文件。但它适用于更高的数字吗?我想知道是否cat要收集所有文件的内容,然后尝试保存到bigtextfile.否则,我想必须有另一种方法来做到这一点,比如获取一个文件,将其附加到bigtextfile,然后获取另一个文件,依此类推。

答案1

在:

cat */* > bigtextfile.txt

shell 将扩展*/*到(非隐藏)匹配文件的排序列表,并将cat使用这些文件路径作为参数执行。

cat将依次打开每个文件并将从文件中读取的内容写入其标准输出。cat内存中一次不会容纳多个充满数据的缓冲区(大约几千字节)。

但您可能会遇到的一个问题是,参数列表cat太大,以至于达到了execve()系统调用参数大小的限制。因此,您可能需要拆分该文件列表并运行cat多次。

您可以使用xargs它(这里使用 GNU 或 BSDxargs作为非标准-r-0选项):

printf '%s\0' */* | xargs -r0 cat -- > big-file.txt

(因为printf是内置在shell中的,所以不经过系统execve调用,所以没有经过它的限制)。

或者find创建文件列表并根据需要运行尽可能多的 cat 命令:

find . -mindepth 2 -maxdepth 2 -type f -exec cat {} + > big-file.txt

或者便携式:

find . -path './*/*' -prune -type f -exec cat {} + > big-file.txt

(请注意,与 相反*/*,它将包含隐藏文件(以及隐藏目录中的文件),而不是在目录的符号链接中查找文件,并且文件列表不会被排序)。

如果在最新版本的 Linux 上,您可以通过执行以下操作取消参数大小的限制:

ulimit -s unlimited
cat -- */* > big-file.txt

通过zsh,您还可以使用zargs

autoload zargs
zargs -- */* -- cat > big-file.txt

通过ksh93,您可以使用command -x

command -x cat -- */* > big-file.txt

所有这些都执行相同的操作,拆分文件列表并cat根据需要运行尽可能多的命令。

再次,你可以使用内置命令来ksh93解决限制:execve()cat

command /opt/ast/bin/cat -- */* > big-file.txt

答案2

Nocat在开始写出之前不会缓冲所有文件。

但是,如果您有大量文件,则可能会遇到传递给 的参数数量问题cat。默认情况下,linux 内核只允许将固定数量的参数传递给任何程序(我不记得如何获取该值,但大多数情况下是几千个)。
要解决这个问题,你可以这样做:

find -mindepth 2 -maxdepth 2 -type f -exec cat {} \; > bigtextfile.txt

这基本上将cat分别调用 . 找到的每个文件find

答案3

如果文件数量太大,*/*将给出太大的参数列表。如果是这样,则可以执行以下操作:

find . -name "*.txt" | xargs cat > outfile

(这个想法是使用find来获取文件名,并将它们放入一个流中;xargs将该流分成可管理的部分以提供给cat,它将它们连接到 的输出流中xargs,然后进入outfile)。

相关内容