6

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

如果您知道一种将wget文件自动下载到这些子目录中的方法,则可以加分。.html因此,如果在顶级路径中有 100 万个页面www.example.com,例如

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

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

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

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

4

3 回答 3

4

另外的选择:

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

或使用parallel

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

-n100一次接受 100 个参数,{#}是作业的序列号。

于 2015-12-25T14:48:34.283 回答
3

您可以通过几个循环运行它,这应该可以解决问题(至少对于文件名的数字部分)。我认为作为单线这样做是过于乐观了。

#! /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 个文件(目标 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 之类的库将更容易优化。

于 2012-06-24T14:17:03.443 回答
3

为了使 ls|parallel 更实用,添加一个变量赋值给目标目录:

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

注意:cd <src_large_dir>执行前。

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

于 2016-02-10T23:42:56.743 回答