How do you to split a very large directory, containing potentially millions of files, into smaller directories of some custom defined maximum number of files, such as 100 per directory, on UNIX?
Bonus points if you know of a way to have wget
download files into these subdirectories automatically. So if there are 1 million .html
pages at the top-level path at www.example.com
, such as
/1.html
/2.html
...
/1000000.html
and we only want 100 files per directory, it will download them to folders something like
./www.example.com/1-100/1.html
...
./www.example.com/999901-1000000/1000000.html
Only really need to be able to run the UNIX command on the folder after wget
has downloaded the files, but if it's possible to do this with wget
as it's downloading I'd love to know!
另外一个选项:
i=1;while read l;do mkdir $i;mv $l $((i++));done< <(ls|xargs -n100)
或使用parallel
:
ls|parallel -n100 mkdir {#}\;mv {} {#}
-n100
需要100个参数在时间和{#}
是作业的序列号。
为了使LS |平行使用更实用,添加一个变量赋值到目标目录:
DST=../brokenup; ls | parallel -n100 mkdir -p $DST/{#}\;cp {} $DST/{#}
注意: cd <src_large_dir>
在执行之前。
以上定义将包含当前目录中的文件的副本的DST,但最多不能超过100个子目录。
您可以通过几个循环的运行它,它应该做的伎俩(至少为文件名的数字部分)。 我认为,这样做的一个班轮是过分乐观。
#! /bin/bash
for hundreds in {0..99}
do
min=$(($hundreds*100+1))
max=$(($hundreds*100+100))
current_dir="$min-$max"
mkdir $current_dir
for ones_tens in {1..100}
do
current_file="$(($hundreds*100+$ones_tens)).html"
#touch $current_file
mv $current_file $current_dir
done
done
我先注释掉做性能测试mkdir $current_dir
和mv $current_file $current_dir
和取消注释touch $current_file
。 这创造了10000个文件(你的100万个文件目标的百分之一)。 一旦文件被创建,我恢复了对脚本编写:
$ time bash /tmp/test.bash 2>&1
real 0m27.700s
user 0m26.426s
sys 0m17.653s
只要你不跨文件系统移动文件,对于每个时间mv
命令应该是恒定的,所以你应该看到类似或更好的性能。 这个比例高达一百万个文件会给你身边27700秒,占46分钟。 有几种途径优化,比如移动的指定目录中的所有文件在一个命令,或去除内的循环。
在做“wget的”抢百万个文件是要采取远远比这更长的时间,并且几乎肯定会需要一些优化; 独自一人在HTTP标头保留带宽将减少几个小时的运行时间。 我不认为一个shell脚本可能为工作的工具; 使用库如WWW ::卷曲CPAN上会更容易优化。