Linux

使用 parallel 將許多目錄拆分為子目錄或併行化此任務

  • November 27, 2017

parallel我想使用或使用其他工具或方法將許多目錄並行拆分為子目錄。

例如,我有 1 000 000 個包含內容的目錄,但是對於一個目錄來說太多了,所以我想在主目錄中創建 10 個目錄並在每個目錄中移動 100 000 個原始目錄。我也想使用按日期排序。我已經在這裡問過類似的問題,但這不是重複的,因為我嘗試了新命令,得到了新結果,現在我重新提出了這個問題。

所以,我已經嘗試過了

ls -tr|parallel -n100000 mkdir "dir_{#}"\;mv {} "dir_{#}" 

還有這個

ls -tr | parallel -j10 -n100000 --no-notice -k 'mkdir -p dir_{#}; mv {} -t dir_{#}' 

命令,但它僅將 ~10 000 移動到一個子目錄中(有時 ~6200,有時 ~12 500)並創建太多子目錄 - 有時比我需要的多 10 倍。

我也試過用這個:

ls -dtr * | parallel -j10 -n100000 --no-notice -k 'mkdir -p dir_{#}; mv {} -t dir_{#}'

但它給了bash: /bin/ls: Argument list too long

當然,我不需要每個子目錄中正好有 100 000 個目錄,它可以是 101 000 或 98 500 個目錄,它應該是 100 000 範圍內的數字

如何並行或使用執行此任務parallel

這個問題處理繁重的 IO。我懷疑這parallel在這種情況下是否真的有用。

無論如何,我建議您考慮一種“傳統”方法:

mkdir dir_{1..10}
ls -tr | nl | \
   awk '$2 !~ /^dir_/ {i=1+int($1/100000); print $2 | "xargs mv -t dir_"i}'

在哪裡

  • ls -tr | nl 按日期對目錄進行排序並添加一個輔助目錄號
  • $2 !~ /^dir_/用於跳過剛剛創建的文件夾。
  • i=1+int($1/100000)根據 dir-number 計算文件夾的編號
  • print $2 | "xargs mv -t dir_"i在沒有過程擴散的情況下移動

如果可能的話,還要比較各自的時間:(time ....並與我們分享結果☺)

問題是shell擴展後命令行可以佔用的字節數有上限,這個限制取決於系統的限制

getconf ARG_MAX

因此,當您達到最大限制時,參數的數量mv {}會根據輸入文件名的長度而變化。

在不放棄使用並行的同時避免此限制的解決方案是將任務分為兩個階段

ls -tr | parallel -N 100000 --pipe -k "mkdir dir_{#}; parallel -X mv -t dir_{#}"

解釋

  • 第一階段使用選項--pipe將標準輸入拆分為確定數量的較小標準輸入,每個標準輸入包含選項指定的 n 行-N。您可以通過使用此範例來觀察效果
seq 1000000 | parallel -N 100000 --pipe wc -l

這給出了 100000 標記處的精確分割

100000
100000
100000
...
  • 在第二階段,內部並行將較小的標準輸入作為他們的新標準輸入來執行他們的工作,該-X選項插入命令行長度允許的盡可能多的參數
mkdir dir_{#}; parallel -X mv -t dir_{#}

引用自:https://unix.stackexchange.com/questions/406906