Shell

遞歸刪除 idx > 10,000 的文件

  • April 6, 2015

問題

在目前工作目錄中,我有幾個(非常多)文件夾,其中一些文件夾中有很多(比如 100,000+)個文件。

我的目標是只獲取包含 10,000 多個文件並刪除folderName10001.ext及以上文件的文件夾(其中folderName包含文件夾的實際名稱,並且ext任何副檔名)。

採取的方法

我正在嘗試nameFolder numberOfFiles使用bash.

find . -maxdepth 1 -type d -name 'acer' -exec sh -c "echo {}; ls {} | wc -l" \;

這工作得很好(對於範例文件夾acer),但輸出是

./acer
6058

我想每個文件夾有 1 行輸出

find . -maxdepth 1 -type d -name 'acer' -exec sh -c "echo {} `ls {} | wc -l`" \;

ls: cannot access {}: No such file or directory


問題

  1. 我怎樣才能在一行中顯示nameFolder numberOfFiles
  2. 有沒有更簡單的方法來刪除每個文件folderName/folderName#.ext,使用#> 10000

問題2

更多細節可能有助於了解正在發生的事情。

我有一個包含以下樹的文件夾

.
├── a
│   ├── a1.ext
│   ├── a2.ext
│   ├── a3.ext
│   └── a4.ext
├── b
│   ├── b1.ext
│   ├── b2.ext
│   ├── b3.ext
│   └── b4.ext
└── c
   ├── c1.ext
   ├── c2.ext
   ├── c3.ext
   └── c4.ext

我想刪除每個數字大於2. (在我的具體情況下,門檻值設置為10000。)


答案 1

這完全取決於解釋了什麼(感謝@Bratchley在評論中的建議)。

由於我正在輸入bash,因此bash首先要解釋我輸入的內容。如果我想bash發送 tofindbash引號,那麼我需要轉義它。

find . -maxdepth 1 -type d -name 'acer' -exec sh -c "echo {} \`ls {} | wc -l;\`" \;

這給了我

./acer 6058

@Barmar 指出引號和雙引號的行為不同,因此

find . -maxdepth 1 -type d -name 'acer' -exec sh -c 'echo {} `ls {} | wc -l`' \;

會工作得很好(注"替換為')。

答案 2

這是由Walter A提供的,它是這個問題的公認答案

更多錯誤(以下是幾個範例)…

black: 390120
./clean.sh: line 6: /bin/ls: Argument list too long
rm: missing operand
Try 'rm --help' for more information.

leather: 118240
./clean.sh: line 6: /bin/ls: Argument list too long
rm: missing operand
Try 'rm --help' for more information.

好的,我已經解決了

ls -d */ | cut -d/ -f1 | while read dir; do
COUNT=$(ls $dir | wc -l);
  if [ ${COUNT} -gt 10000 ]; then
     echo "$dir: ${COUNT}" ;
     for i in `seq 10001 ${COUNT}`; do
        rm ${dir}/${dir}${i}.*
     done
  fi
done

你可以寫

ls -d */ | while read dir; do
   echo "$dir: $(ls $dir | wc -l)"
done

當文件名沒有前導零編號時,您可以嘗試

ls -d */ | cut -d/ -f1 | while read dir; do
    COUNT=$(ls $dir | wc -l);
    echo "$dir: ${COUNT}" ;
    if [ ${COUNT} -gt 10000 ]; then
       ls ${dir}/${dir}?????*.ext | grep -v ${dir}/${dir}10000.ext | xargs rm
    fi
done

當文件名中有前導零時,另一種方法是可能的:

ls -d */ | cut -d/ -f1 | while read dir; do
  ls ${dir}/${dir}*.ext | tail -n +10001 | xargs rm
done

編輯:在 ls 命令中包含 dir+filename,我添加cut -d/ -f1 |以切斷尾隨 /。

使用單引號而不是雙引號,這樣反引號$就不會被原始 shell 解釋:

find . -maxdepth 1 -type d -name 'acer' -exec sh -c 'echo {} $(ls {} | wc -l)' \;

對於第二個問題,我會將您想要做的事情放入一個單獨的腳本中,該腳本將目錄名稱作為參數。然後做:

find . -maxdepth 1 -type d -name 'acer' -exec ./scriptname {} \;

這樣您就不必處理使用-exec sh -c.

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