将所有子文件夹中的所有文本文件连接成一个巨大的文本文件

将所有子文件夹中的所有文本文件连接成一个巨大的文本文件

好吧,情况是我有未知数量的子目录,它们都遵循相同的命名配置文件

文件夹0、文件夹1、文件夹2、文件夹3等

现在每个文件夹将有 3 个文本文件,并且这些文本文件在所有文件夹中将具有相同的 3 个文件名

文件1 文件2 文件3

我想找到一种简单的方法将所有文件夹中的所有文本文件连接成一个文本文件,从文件夹0开始,文件1,然后文件2,然后文件3,所有文件夹中的顺序相同。

现在对于少量文件夹我可以使用 cat

cat folder0/file1 folder0/file2 folder0/file3 folder1/file1 folder1/file2 folder1/file3 folder2/file1 folder2/file2 folder2/file3 folder3/file1 folder3/file2 folder3/file3 > textfile

但文件夹的数量未知,可能有 100 或 1000 个

任何人都知道可以完成此任务的脚本。

答案1

仅使用 unix 工具和管道:

find ./ -type f -regex './folder[0-9]+/file[0-9]+' -print0 | sort -zV | xargs --null cat

解释:

find搜索符合某些条件的所有文件

  1. ./告诉find从您当前所在的位置(即您的工作目录)进行搜索
  2. -type f告诉find仅查找文件,以防存在名为文件的目录
  3. -regex指示find仅搜索文件的整个路径与给定模式匹配的文件。在这种情况下,“./folder”后跟一位或多位数字,然后是新目录,然后是“file”,后跟一位或多位数字。
  4. -print0告诉find输出它发现的由空字符分隔的文件,这保证不会出现在文件名中,并且即使您的文件名包含换行符也能工作,它们可以

sort对它得到的列表进行排序

  1. 告诉对空字符分隔的条目进行排序,而不是像默认情况那样对换行符分隔的条目进行-z排序sort
  2. 告诉-V我们sort对条目进行排序,就像人类直观地对它们进行排序一样,即file11在 和 后面,file1file2不是在中间。

xargs只是使用它获取的条目并将它们作为参数传递给cat.--null告诉你xargs,你猜对了,通过它们之间的空字符来区分不同的条目,而不是空格或换行符。

答案2

zsh

autoload zargs
zargs -r -- folder<->/file<1-3>(nN) -- cat > hugefile

使用bash、 和 GNU 工具:

shopt -s extglob nullglob
print0() { (( $# == 0 )) || printf '%s\0' "$@"; }
 
xargs -r0a <(
  print0 folder+([0123456789])/file[123] | sort -zV
  ) cat > hugefile

其中+([0123456789])(使用extglob它可以启用一些 ksh 的高级 glob 运算符,包括+(...))相当于 zsh 的<->(任何 ASCII 十进制数字序列),GNUsort -V相当于 zsh 的nglob 限定符(用于数字排序,以便folder10位于之后folder9而不是之间和folder1之间folder2)默认字母排序),nullglob对于Nglob 限定符,GNUxargs用于代替 zshzargs来分割列表以避免arg 列表太长错误。

我们定义了一个print0函数,它打印其参数 NUL 分隔(因为 bash 没有zsh's ),但在这里,考虑到文件路径不会包含任何withoutprint -rNC1特有的字符,我们不妨将它们打印为换行符分隔并忽略这样一个事实:如果列表为空,它会打印一个空行,因为无论如何都会忽略该行。xargs-0printf '%s\n'xargs

答案3

达到一定数量的文件夹后,您可以执行以下操作:

cat folder*/* > file

或者,仅针对特定文件/目录:

cat {folder1,folder2,folder3}/{file1,file2,file3} > file

如果名称确实由固定字符串和连续数字组成,您可以进一步简化为

cat folder{1..3}/file{1..3} > file

现在,如果您有大量文件和文件夹,这将会失败,但它应该适用于大多数情况。例如,在我的计算机上,我使用以下命令在 1000 个目录中创建了 3000 个文件:

mkdir folder{1..1000}
touch folder{1..1000}/file{1..3}
for f in */*; do echo "$f" > $f; done

然后将所有文件连接成一个:

cat folder*/* > file

这给出了一个包含 3000 行的文件。

但是,如果您遇到问题,您可以随时使用find

find folder1 folder2 folder3 -name "file[123]" -exec cat {} + > file

或者

find folder* -name "file[123]" -exec cat {} + > file

警告:这些方法都不会让您指定顺序,但它们在所有目录中应该具有相同的顺序。

相关内容