我在一个目录中有大量文件,目前有 10,804 个文件。文件数量可以在 5 到 100,000 之间浮动。
我正在寻找一种方法,将每 250 个单独的文件合并为一个大文件,其余文件合并为一个小文件。例如 1200 个文件,我想要 4 个 250 个文件和 1 个 200 个文件
我正在使用 bash shell。
答案1
您可以编写一个简单的循环来使用数组来执行此操作,并且${x:s:l}
参数扩展:
files=(*)
for (( i = 0; i < ${#files[@]}; i += 250 ))
do
cat -- "${files[@]:$i:250}" > "file$i.combined"
done
在这里,我们将所有(非隐藏)文件收集.
到一个数组中files
(文件名按词法排序),并从 0 循环计数到 250 秒内有多少个文件。对于每个 250,我们将文件名(0-249、250-499 等)展开为参数,并将cat
输出放入file0.combined
、file250.combined
等中。
这只是传统 C 风格for
循环的 Bash 版本。因为无论如何你都必须为每个单独的循环循环cat
,所以没有太多必要让事情变得过于复杂。
.combined
最后您将得到几个文件 - 因为文件名已经扩展,这些文件将不会再次包含在串联中,但如果您第二次运行该命令,它们就会包含在串联中。如果这是一个问题,您可以将它们放在其他地方,然后删除它们,或者如果它直接发送到打印机,甚至只是通过管道传输到lp
.
答案2
简单地:
#!/bin/bash
files_count=`ls -1 ./ | wc -l`
block_size=10
blocks_count=$(($files_count/$block_size))
for i in $(seq 1 1 $blocks_count); do
files=`find . -type f -exec readlink -f {} \; | head -$block_size`
for j in $files; do
if [ -f $j ] && [[ "$j" != outfile* ]] ; then
cat $j >> outfile$i
fi
done
done
# remainder part
for i in *; do
if [ -f $i ] && [[ "$i" != outfile* ]] ; then
cat $i >> outfilelast
fi
done
笔记:
您的文件按字母顺序合并,脚本也应放置在同一目录中。
答案3
我尝试用下面的方法
for ((i=1;i<=1200;i++)); do j=$(($i + 249 )); sed -n ''$i','$j'p' filename >individual_$i ;i=$j; done
答案4
假设您可以按照find
找到它们的顺序组合它们:
find . -maxdepth 1 -type f -print0 |
xargs -0 -L 250 sh -c 'cat "$@" >/tmp/combined-${1##*/}' sh
file-1
对于包含名称最多为file-739
(作为示例)的文件的目录,这将创建/tmp
名为combined-file-1
、
combined-file-251
和 的文件combined-file-501
,其中后面的位combined-
是该组合文件中第一个文件的名称。
cat
它通过调用重复执行的内联 shell 脚本来批量连接文件,一次最多连接 250 个文件xargs
(${1##*/}
该脚本中的 会从当前批处理的第一个文件的路径名中删除任何目录路径)来实现此目的。该xargs
实用程序从 中获取以 null 结尾的字符串形式的文件名find
。该find
实用程序将(仅)查找当前目录并输出其中与常规文件相对应的所有路径名。
然后您将打印这些/tmp/combined-*
文件。
要仅处理具有特定后缀的文件,例如.txt
,请-name '*.txt'
在find
命令中使用 before -print0
。
-print0
通常执行的操作和find
选项-0
是xargs
非标准的。