在本質上是 BSD 的終端機中運行 MacOS,因此在這裡發布我的問題而不是詢問不同。我想透過隨機刪除檔案來在後續步驟中修剪圖像資料集。有些目錄有超過 100 萬張 jpg。我的資料位於主目錄中,子目錄的最大深度僅為 1:
-master
-data1
image.jpgs
-data2
image.jpgs
-data3
image.jpgs
-data4
image.jpgs
... and so forth
我找到了這個連結:
https://superuser.com/questions/1186350/delete-all-but-1000-random-files-in-a-directory
……並想出了:
for f in *.jpg; do find "$f" -type f -print0 | sort -R | tail -n +50001 | xargs -0 rm; done
雖然它確實有效,但我希望它能夠對子目錄遞歸地執行此操作,因此我不必為每個目錄手動執行此操作。所以我的問題/要求是:
- 我可以以某種方式優化它以加快速度嗎?
- sort/tail 遇到檔案少於 50,000 個的目錄時會回傳錯誤嗎?
答案1
檢查了連結的來源貼文後,看起來您的循環實際上應該是:
for d in */; do find "$d" -iname '*.jpg' -type f -print0 | sort -zR | tail -zn +50001 | xargs -0r rm; done
從目錄運行master
。
和-z
的選項是必需的,因為輸入是空分隔的。如果少於 50000 行,兩者都不會抱怨 -不關心也不會輸出任何內容,因為第 50000 行之後沒有任何內容。可能會抱怨在沒有參數的情況下運行,但是如果沒有輸入,GNU 的選項將阻止它運行(BSD xargs 不需要它,但可能不會抱怨)。sort
tail
sort
tail
rm
-r
xargs
rm
最後但最重要的是,-z
BSD tail 可能不支援 null 分隔輸入的選項。您需要 GNU tail,它可以使用自製程式安裝。
如果您的檔案名稱保證其中不包含空格、換行符號、引號、反斜線等,那麼您可能可以不使用空白分隔行。在這種情況下:
for d in */; do find "$d" -type f | sort -R | tail -n +50001 | xargs rm; done