デフォルトでは、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
作業中に、サブディレクトリに対してこの操作を繰り返し実行して、各ディレクトリに対して手動で実行する必要がないようにしたいと思います。私の質問/要件は次のとおりです。
- スピードを上げるために何とか最適化できますか?
- 50,000個未満のファイルを含むディレクトリが見つかった場合、sort / tailはエラーを返しますか?
答え1
リンクされたソース投稿を確認したら、ループは実際には次のようになります。
for d in */; do find "$d" -iname '*.jpg' -type f -print0 | sort -zR | tail -zn +50001 | xargs -0r rm; done
ディレクトリから実行しますmaster
。
-z
入力はNULLで区切られているため、オプションが必要です。行が50,000未満の場合でも文句はありません。 50,000行目以降は何もないため、何も気にしないでください。引数なしで実行することについて文句を言うことができますが、GNUのオプションは入力なしで実行されるのを防ぎます(BSD xargsはそれを要求しませんが、おそらく文句を言わないでしょう)。sort
tail
sort
tail
rm
-r
xargs
rm
最後に、-z
BSDテールはnullで区切られた入力オプションをサポートしていない可能性があります。 homebrewを使用してインストールできるGNUテールが必要です。
ファイル名にスペース、改行、引用符、バックスラッシュなどが含まれないことが保証されている場合、行を区切るためにスペースは必要ありません。この場合:
for d in */; do find "$d" -type f | sort -R | tail -n +50001 | xargs rm; done