如何将子目录拆分为/ bin / cat的较小块

时间:2014-02-17 17:56:10

标签: bash cat

我有以下情况。一个包含很多子目录的目录,每个子目录都包含一个我想要连接的感兴趣的文件。 如,

my_dir/
    subdir1/
            subsubdir/
                file_of_interest1.txt
                ...
    subdir2/
            subsubdir/
                file_of_interest1.txt
                ...
    ...

现在,我尝试使用cat my_dir/*/*/*.txt > all.txt
但不幸的是,子目录树太大了,我得到以下错误:

bash: /bin/cat: Argument list too long

是否有一种巧妙的方法来规避问题,例如,通过将文件连接成较小的块? 例如,连接1/3的子目录,然后是另外的1/3和1/3,然后将它们连接在一起?

1 个答案:

答案 0 :(得分:3)

find浏览文件并尽可能多地添加到每个cat调用的命令行:

find . -type f -name '*.txt' -exec cat '{}' + >all.txt

如果您的find不支持-exec ... {} +(如果符合当前版本的POSIX规范应该如此),还有一种使用GNU扩展来使xargs安全的方法:

find . -type f -name '*.txt' -print0 | xargs -0 cat >all.txt

使用不带-0的xargs是不安全的 - 在这种情况下,它没有正确处理带换行符的文件名,以及其他问题(其中一些但不是所有问题都可以通过其他选项避免)。考虑一个恶意用户创建文件$'foo \n/etc/passwd' - 您不希望冒着将/etc/passwd注入输出的风险。

最后,使用find -exec的效率较低,较旧的方式(为每个找到的文件调用cat的单独副本):

find . -type f -name '*.txt' -exec cat '{}' ';' >all.txt

...或者,在类似的惩罚下(多次调用cat),您只需在shell脚本中使用循环:

for f in my_dir/*/*/*.txt; do
  cat "$f"
done >all.txt

请注意,这会对整个循环进行重定向,而不是(基于每个文件)效率较低。


除此之外:如果使用POSIX sh或bash,则不需要引用{}。但是,如果您尝试支持{},则执行需要引用zsh,所以我在此处这样做。