我想将数千个小文本文件合并成一个大文本文件。我将它们放在具有以下结构的目录中: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)
Nocat
在开始写出之前不会缓冲所有文件。
但是,如果您有大量文件,则可能会遇到传递给cat
. 默认情况下,Linux 内核只允许将固定数量的参数传递给任何程序(我不记得如何获取该值,但在大多数情况下是几千个)。
要解决此问题,您可以执行以下操作:
find -mindepth 2 -maxdepth 2 -type f -exec cat {} \; > bigtextfile.txt
Run Code Online (Sandbox Code Playgroud)
这基本上会cat
分别调用find
.