sod*_*ate 25 find brace-expansion files cat
我有大约 15,000 个名为file_1.pdb、file_2.pdb等的文件。我可以通过执行以下操作来按顺序对其中的几千个文件进行分类:
cat file_{1..2000}.pdb >> file_all.pdb
Run Code Online (Sandbox Code Playgroud)
但是,如果我对 15,000 个文件执行此操作,则会出现错误
-bash: /bin/cat: Argument list too long
Run Code Online (Sandbox Code Playgroud)
我已经看到通过这样做解决了这个问题,find . -name xx -exec xx但这不会保留文件加入的顺序。我怎样才能做到这一点?
Kus*_*nda 51
使用find,sort和xargs:
find . -maxdepth 1 -type f -name 'file_*.pdb' -print0 |
sort -zV |
xargs -0 cat >all.pdb
Run Code Online (Sandbox Code Playgroud)
该find命令查找所有相关文件,然后将它们的路径名打印出来,然后sort执行“版本排序”以按正确的顺序排列它们(如果文件名中的数字已零填充到固定宽度,我们将不需要-V)。xargs获取此排序路径名列表并cat尽可能大批量地运行这些路径名。
即使文件名包含奇怪的字符(如换行符和空格),这也应该有效。我们使用-print0withfind来给出以sort空字符结尾的名称进行排序,并sort使用-z. xargs也用它的-0标志读取以空字符结尾的名字。
请注意,我将结果写入名称与模式不匹配的文件file_*.pdb。
上述解决方案对某些实用程序使用了一些非标准标志。这些实用程序的 GNU 实现以及至少 OpenBSD 和 macOS 实现都支持这些。
使用的非标准标志是
-maxdepth 1, 使find只进入最顶层目录而不进入子目录。POSIXly,使用find . ! -name . -prune ...-print0, 使find输出以 nul 结尾的路径名(这被 POSIX 考虑但被拒绝)。可以-exec printf '%s\0' {} +改用。-z, 制作sort以空结尾的记录。没有 POSIX 等价。-V,sort例如200在之后进行排序3。没有 POSIX 等效项,但如果文件名具有固定前缀,则可以用文件名特定部分的数字排序替换。-0, 使xargs读取以空字符结尾的记录。没有 POSIX 等价。POSIXly,需要以xargs.如果路径名很乖,如果目录结构是平的(无子目录),那么可以凑合没有这些标志,除了-V有sort。
Sté*_*las 14
与zsh(该{1..15000}运算符来自哪里):
autoload zargs # best in ~/.zshrc
zargs file_{1..15000}.pdb -- cat > file_all.pdb
Run Code Online (Sandbox Code Playgroud)
或者对于file_<digits>.pdb按数字顺序排列的所有文件:
zargs file_<->.pdb(n) -- cat > file_all.pdb
Run Code Online (Sandbox Code Playgroud)
(其中<x-y>是一个匹配十进制数 x 到 y 的 glob 运算符。没有xnor y,它是任何十进制数。相当于extendedglob's[0-9]##或kshglob's +([0-9])(一个或多个数字))。
随着ksh93,利用其内置cat的命令(所以不会受的该限制execve()系统调用,因为没有执行):
command /opt/ast/bin/cat file_{1..15000}.pdb > file_all.pdb
Run Code Online (Sandbox Code Playgroud)
与bash/ zsh/ ksh93(支持zsh's{x..y}并具有printf内置):
printf '%s\n' file_{1..15000}.pdb | xargs cat > file_all.pdb
Run Code Online (Sandbox Code Playgroud)
在 GNU 系统或兼容系统上,您还可以使用seq:
seq -f 'file_%.17g.pdb' 15000 | xargs cat > file_all.pdb
Run Code Online (Sandbox Code Playgroud)
对于xargs基于 - 的解决方案,必须特别注意包含空格、单引号或双引号或反斜杠的文件名。
像 for 一样-It's a trickier filename - 12.pdb,使用:
seq -f "\"./-It's a trickier filename - %.17g.pdb\"" 15000 |
xargs cat > file_all.pdb
Run Code Online (Sandbox Code Playgroud)
小智 12
for 循环是可能的,而且非常简单。
for i in file_{1..15000}.pdb; do cat $i >> file_all.pdb; done
Run Code Online (Sandbox Code Playgroud)
缺点是你调用cat了很多次。但是,如果您不能确切地记住如何使用这些东西find并且调用开销在您的情况下不算太糟糕,那么值得记住。