2012-06-23 40 views
4

如何將包含潛在數百萬個文件的超大目錄拆分爲一些自定義最大數量的文件的較小目錄,例如每個目錄100個,在UNIX上?單行將Unix上的超大目錄拆分爲更小的目錄

獎勵積分,如果你知道的方式有wget自動下載文件到這些子目錄。因此,如果有100萬.html頁處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下載文件時執行此操作,我很想知道!

+0

文件名中是否需要逗號?他們會讓解決方案變得更加複雜。 –

+0

不一定,但下載的文件在技術上可以包含任何內容(其中很多包含逗號,以及這些字符:'?,:; /%{} [] $&*^@!〜'')。 –

+0

好吧,現在我很困惑......如果你的文件名包含一堆特殊字符,你將如何創建目錄名?在你的例子中,這些目錄包含一系列數字......文件名是格式爲「{name-including-special-characters} {number} .html'? –

回答

2

你可以通過幾個循環來運行它,它應該做到這一點(至少對於文件名的數字部分)。我認爲這樣做是一個單一的過程樂觀。

#! /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分鐘。有幾種優化的途徑,例如在一個命令中移動給定目錄的所有文件,或者刪除inner for循環。

做'wget'來抓取一百萬個文件需要花費更長的時間,而且幾乎肯定會需要一些優化;僅在http標頭中保留帶寬將會減少運行時間達數小時。我不認爲shell腳本可能是這項工作的正確工具;在cpan上使用諸如WWW :: Curl之類的庫將更容易優化。

1

另一種選擇:

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

或者使用parallel

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

-n100在同一時間需要100個參數和{#}是工作的序列號。執行前cd <src_large_dir>:|

1

爲了使LS平行更實際的使用,一個變量賦值添加到目標目錄:

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

注意。

上面定義的DST將包含當前目錄文件的副本,但每個子目錄最多包含100個副本。