在Unix上将非常大的目录分割成更小的目录

如何在UNIX上将包含潜在的数百万个文件的非常大的目录拆分成一些自定义的最大数量的文件(如每个目录100个)的较小目录?

奖金点,如果你知道一个方法有wget下载文件到这些子目录自动。 因此,如果www.example.com顶层path中有100万个.html页面,

 /1.html /2.html ... /1000000.html 

而我们只需要每个目录100个文件,就会把它们下载到类似的文件夹中

 ./www.example.com/1-100/1.html ... ./www.example.com/999901-1000000/1000000.html 

只有真正需要能够在wget下载文件之后才能在文件夹上运行UNIX命令,但是如果可以在wget下载文件时执行此操作,我很想知道!

你可以通过几个循环来执行这个操作,至少对于文件名的数字部分来说是这样的。 我认为这样做是一个单一的过程乐观。

 #! /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_dirmv $current_file $current_dir并取消注释touch $current_file 。 这创建了10000个文件(1000000个文件的目标的百分之一)。 一旦这些文件被创建,我就回到了脚本,如下所示:

 $ time bash /tmp/test.bash 2>&1 real 0m27.700s user 0m26.426s sys 0m17.653s 

只要不跨文件系统移动文件,每个mv命令的时间应该是不变的,所以你应该看到相似或更好的性能。 缩放到一百万个文件将会给你大约27700秒,即46分钟。 有几种优化的途径,例如在一个命令中移动给定目录的所有文件,或者删除内部for循环。

做'wget'来抓取一百万个文件将花费比这更长的时间,并且几乎肯定会需要一些优化; 仅在http头文件中保留带宽将使运行时间缩短数小时。 我不认为shell脚本可能是这个工作的正确工具; 在cpan上使用诸如WWW :: Curl之类的库将更容易优化。

另外一个选择:

 i=1;while read l;do mkdir $i;mv $l $((i++));done< <(ls|xargs -n100) 

或者使用parallel

 ls|parallel -n100 mkdir {#}\;mv {} {#} 

-n100取100个参数, {#}是作业的序列号。

要使ls | parallel更加实用,请在目标dir中添加一个变量赋值:

 DST=../brokenup; ls | parallel -n100 mkdir -p $DST/{#}\;cp {} $DST/{#} 

注意: cd <src_large_dir>在执行之前。

上面定义的DST将包含当前目录文件的副本,但每个子目录最多为100个。