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

xyz*_*xyz 4 files cat

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

cat */* > bigtextfile.txt
Run Code Online (Sandbox Code Playgroud)

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

Sté*_*las 10

在:

cat */* > bigtextfile.txt
Run Code Online (Sandbox Code Playgroud)

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

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

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

您可以使用xargs它(此处使用 GNU 或 BSDxargs用于非标准-r-0选项):

printf '%s\0' */* | xargs -r0 cat -- > big-file.txt
Run Code Online (Sandbox Code Playgroud)

(因为printf是在 shell 中构建的,它不会通过execve系统调用,所以不会通过它的限制)。

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

find . -mindepth 2 -maxdepth 2 -type f -exec cat {} + > big-file.txt
Run Code Online (Sandbox Code Playgroud)

或者便携:

find . -path './*/*' -prune -type f -exec cat {} + > big-file.txt
Run Code Online (Sandbox Code Playgroud)

(注意,尽管与 相反*/*,它将包含隐藏文件(和隐藏目录中的文件),而不是在指向目录的符号链接中查找文件,并且不会对文件列表进行排序)。

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

ulimit -s unlimited
cat -- */* > big-file.txt
Run Code Online (Sandbox Code Playgroud)

使用zsh,您还可以使用zargs

autoload zargs
zargs -- */* -- cat > big-file.txt
Run Code Online (Sandbox Code Playgroud)

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

command -x cat -- */* > big-file.txt
Run Code Online (Sandbox Code Playgroud)

所有这些都做同样的事情,拆分文件列表并cat根据需要运行尽可能多的命令。

随着ksh93再次,让您可以在execve()使用内置限制cat命令:

command /opt/ast/bin/cat -- */* > big-file.txt
Run Code Online (Sandbox Code Playgroud)


phe*_*mer 5

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

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

find -mindepth 2 -maxdepth 2 -type f -exec cat {} \; > bigtextfile.txt
Run Code Online (Sandbox Code Playgroud)

这基本上会cat分别调用find.