好吧,情况是我有未知数量的子目录,它们都遵循相同的命名配置文件
文件夹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
搜索符合某些条件的所有文件
./
告诉find
从您当前所在的位置(即您的工作目录)进行搜索-type f
告诉find
仅查找文件,以防存在名为文件的目录-regex
指示find
仅搜索文件的整个路径与给定模式匹配的文件。在这种情况下,“./folder”后跟一位或多位数字,然后是新目录,然后是“file”,后跟一位或多位数字。-print0
告诉find
输出它发现的由空字符分隔的文件,这保证不会出现在文件名中,并且即使您的文件名包含换行符也能工作,它们可以
sort
对它得到的列表进行排序
- 告诉对空字符分隔的条目进行排序,而不是像默认情况那样对换行符分隔的条目进行
-z
排序sort
- 告诉
-V
我们sort
对条目进行排序,就像人类直观地对它们进行排序一样,即file11
在 和 后面,file1
而file2
不是在中间。
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 的n
glob 限定符(用于数字排序,以便folder10
位于之后folder9
而不是之间和folder1
之间folder2
)默认字母排序),nullglob
对于N
glob 限定符,GNUxargs
用于代替 zshzargs
来分割列表以避免arg 列表太长错误。
我们定义了一个print0
函数,它打印其参数 NUL 分隔(因为 bash 没有zsh
's ),但在这里,考虑到文件路径不会包含任何withoutprint -rNC1
特有的字符,我们不妨将它们打印为换行符分隔并忽略这样一个事实:如果列表为空,它会打印一个空行,因为无论如何都会忽略该行。xargs
-0
printf '%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
警告:这些方法都不会让您指定顺序,但它们在所有目录中应该具有相同的顺序。