フォルダーが数十万の小さなファイルで扱いにくくなるという問題があります。
非常に多くのファイルがあり、rm -rf
を実行するとエラーが返されます。代わりに、次のようにする必要があります。
find /path/to/folder -name "filenamestart*" -type f -exec rm -f {} \;
これは機能しますが、非常に遅く、常にメモリ不足が原因で失敗します。
これを行うより良い方法はありますか?理想的には、中身を気にせずにディレクトリ全体を削除したいと思います。
Rsyncの使用は驚くほど速くて簡単です。
mkdir empty_dir
rsync -a --delete empty_dir/ yourdirectory/
@sarathの答えは、もう1つの速い選択であるPerlに言及しました。そのベンチマークはrsync -a --delete
よりも高速です。
cd yourdirectory
Perl -e 'for(<*>){((stat)[9]<(unlink))}'
出典:
Twitter の誰かが-delete
の代わりに -exec rm -f{} \;
これによりコマンドの効率が向上しましたが、再帰を使用してすべてを処理します。
次のようなものはどうですか:find /path/to/folder -name "filenamestart*" -type f -print0 | xargs -0rn 20 rm -f
パラメータ-n
の引数を変更することで、一度に削除するファイルの数を制限できます。空白のファイル名も含まれます。
巧妙なトリック:
rsync -a --delete empty/ your_folder/
これはCPUを非常に集中的に使用しますが、本当に高速です。 https://web.archive.org/web/20130929001850/http://linuxnote.net/jianingy/en/linux/a-fast-way-to-remove-huge-number-of-filesを参照してください.html
コメントの1つを拡張すると、自分がやっていることをやっているとは思いません。
最初に、状況をシミュレートするために大量のファイルを作成しました。
$ mkdir foo
$ cd foo/
$ for X in $(seq 1 1000);do touch {1..1000}_$X; done
次に、私が失敗すると予想していたことと、質問であなたがやっているように聞こえることを試しました。
$ rm -r foo/*
bash: /bin/rm: Argument list too long
しかし、これは行う動作します:
$ rm -r foo/
$ ls foo
ls: cannot access foo: No such file or directory
-delete
と比較して-exec rm \{\} \;
をテストする機会があり、-delete
がこの問題の答えでした。
-delete
を使用すると、40万ファイルのフォルダー内のファイルがrm
より少なくとも1,000倍高速に削除されました。
「Linuxで多数のファイルを削除する方法」の記事は、約3倍高速であることを示唆していますが、私のテストでは、違いははるかに劇的でした。
上記の-delete
オプションについて:作成した一時フォルダ内の大量の(100万以上の)ファイルを誤って削除し、誤って毎晩クリーンアップするのを忘れていました。誤ってディスク/パーティションをいっぱいにしてしまい、find .
コマンド以外の方法でそれらを削除できませんでした。それは遅いですが、最初は私が使っていました:
find . -ls -exec rm {} \;
しかし、それにはかなりの時間がかかりました。一部のファイルを削除するために約15分後に開始されましたが、最終的に開始されてから1秒あたり10未満程度しか削除されていなかったと思います。だから、私は試してみました:
find . -delete
代わりに、今すぐ実行します。他のコマンドとは異なり、CPUに非常に負担をかけていますが、実行速度は速くなっているようです。それは1時間ほど実行されており、ドライブとパーティションのスペースが徐々に「スリム化」しているように見えますが、それでも非常に長い時間がかかります。それが他の1,000倍の速さで実行されていることを真剣に疑っています。すべての場合と同様に、空間と時間のトレードオフを指摘したかっただけです。余裕のあるCPU帯域幅がある場合(私たちはそうします)、後者を実行します。それは私のCPUを実行しています(uptime
レポート):
10:59:17 up 539 days, 21:21, 3 users, load average: 22.98, 24.10, 22.87
また、負荷の平均が30.00を超えるのを見たことがありますが、これはビジーなシステムには適していませんが、通常は負荷が軽いため、数時間は問題ありません。私はシステム上の他のほとんどのものをチェックしましたが、それらはまだ反応しているので、今のところ大丈夫です。
Btrfsボリュームの使用を検討し、多数のファイルがあるこのようなディレクトリのボリューム全体を削除してください。
または、FSイメージファイルを作成してから、そのファイルをマウント解除して削除することで、すべてを一度に非常に高速に削除できます。
rm -rf directory
の代わりにrm -rf *
を使用してください。内容をクリアするためにディレクトリにいる間、私たちは最初にrm -rf *
を行っていましたが、それは可能な限り速いと考えました。しかし、それから 上級エンジニア の1人がアスタリスク(*
)の使用を避け、代わりにrm -rf directory
のような親ディレクトリを渡すことを提案しました。
それが違いを生まない方法についての激しい議論の後、find
を使用する3番目の方法とともに、それをベンチマークすることにしました。結果は次のとおりです。
time rm -rf * 2m17.32s
time rm -rf directory 0m15.60s
time find directory -delete 0m16.97s
rm -rf directory
はrm -rf *
よりも約9倍高速です!
言うまでもなく、私たちは あのエンジニア ビールを買いました!
そのため、rm -rf directory; mkdir directory
を使用してディレクトリを削除し、再作成します。
Linuxで多数のファイルを削除するために使用できる方法がいくつかあります。 execオプションよりも高速な、find with deleteオプションを使用できます。その後、Perlのリンク解除、さらにはrsyncを使用できます。 Linuxで多数のファイルを削除する方法
GNU parallel
がインストールされていると仮定して、これを使用しました:
parallel rm -rf dir/{} ::: `ls -f dir/`
そしてそれは十分に速かった。
REALLY LARGEディレクトリを削除するには、私が this site から学んだように、別のアプローチが必要です。ioniceを使用する必要があります。(-c3を使用して)削除が確実に実行されるのは、システムにIO-がある場合のみです。それのための時間。システムの負荷は高くなりませんが、すべてが応答性を維持します(ただし、findのCPU時間は約50%と非常に高かったです)。
find <dir> -type f -exec ionice -c3 rm {} \;
数百万のファイルがあり、上記のすべての解決策でシステムにストレスがかかる場合は、次のインスピレーションを試すことができます。
ファイルNice_delete
:
#!/bin/bash
MAX_LOAD=3
FILES=("$@")
BATCH=100
while [ ${#FILES[@]} -gt 0 ]; do
DEL=("${FILES[@]:0:$BATCH}")
ionice -c3 rm "${DEL[@]}"
echo -n "#"
FILES=("${FILES[@]:$BATCH}")
while [[ $(cat /proc/loadavg | awk '{print int($1)}') -gt $MAX_LOAD ]]; do
echo -n "."
sleep 1
done
done
そして今ファイルを削除します:
find /path/to/folder -type f -exec ./Nice_delete {} \+
Findは、数万のファイルのバッチ(getconf ARG_MAX
を参照)を作成し、Nice_delete
に渡します。これにより、さらに小さなバッチが作成され、過負荷が検出されたときにスリープできるようになります。
それらのファイルを取り除く必要があるかどうかに応じて、shred
を使用することをお勧めします。
$ shred -zuv folder
ディレクトリを削除したいが、削除して再作成することができない場合は、すぐに移動して再作成することをお勧めします。
mv folder folder_del
mkdir folder
rm -rf folder_del
変更する必要があるのは1つのiノードだけなので、これはより速く、信じられないかもしれません。覚えておいてください。マルチコアコンピューターでは、この味を実際に並列化することはできません。それは、RAIDまたはあなたが持っているものによって制限されるディスクアクセスに帰着します。
Pythonスクリプトは不潔なものとして排除すべきではありません。
#!/usr/bin/python3
import shutil
path_for_deletion = input( 'path of dir for deletion> ' )
print( 'about to remove ' + path_for_deletion + ' ...' )
shutil.rmtree( path_for_deletion, ignore_errors=True )
print( '... done' )
私は、さまざまな方法のいくつかの有用なベンチマークを行った人 here にこれをベンチマークしてみることができるかどうか尋ねました。私の実験から、それはかなり良いようです。
NBエラーは、少なくともそれらを出力するために処理できますが、後でtrash myDirectoryForDeletion
またはrm -rfv myDirectoryForDeletion
を実行する方が簡単な場合があります。
できるだけ早く多くのファイルを削除したい場合は、ls -f1 /path/to/folder/with/many/files/ | xargs rm
は問題なく動作する可能性がありますが、システムがIO問題になり、削除操作中にアプリケーションがスタックする可能性があるため、運用システムでは実行しないことをお勧めします。
このスクリプトは多くのファイルに対して適切に機能し、システムのioloadに影響を与えるべきではありません。
#!/bin/bash
# Path to folder with many files
FOLDER="/path/to/folder/with/many/files"
# Temporary file to store file names
FILE_FILENAMES="/tmp/filenames"
if [ -z "$FOLDER" ]; then
echo "Prevented you from deleting everything! Correct your FOLDER variable!"
exit 1
fi
while true; do
FILES=$(ls -f1 $FOLDER | wc -l)
if [ "$FILES" -gt 10000 ]; then
printf "[%s] %s files found. going on with removing\n" "$(date)" "$FILES"
# Create new list of files
ls -f1 $FOLDER | head -n 5002 | tail -n 5000 > "$FILE_FILENAMES"
if [ -s $FILE_FILENAMES ]; then
while read FILE; do
rm "$FOLDER/$FILE"
sleep 0.005
done < "$FILE_FILENAMES"
fi
else
printf "[%s] script has finished, almost all files have been deleted" "$(date)"
break
fi
sleep 5
done
上記のイズカタのヒント:
しかし、これは機能します:
$ rm -r foo/ $ ls foo ls: cannot access foo: No such file or directory
これはほぼ機能しました-または機能しました-しかし、許可にいくつかの問題がありました。ファイルはサーバー上にありましたが、このアクセス許可の問題がどこから発生したのかわかりません。とにかく、ターミナルはすべてのファイルについて確認を求めました。ファイルの量は約20 000だったので、これはオプションではありませんでした。 「-r」の後にオプション「-f」を追加したため、コマンド全体は「rm -r -ffoldername/ = "。それからそれはうまくいくように見えました。私はターミナルの初心者ですが、大丈夫だったと思いますよね?ありがとう!
ls -1 | xargs rm -rf
メインフォルダ内で動作するはずです
使用する ls -f | xargs -n 5000 rm
、調整中-n
システムに応じたバッチサイズ(_digital_infinityのkudosは-n
ヒント)。
さらに、インラインgrepを使用してリストをフィルタリングできます。 ls -f | grep '^156' | xargs -n 5000 rm
。
私の経験では、これはfindを使用する手法よりもはるかに高速で、より複雑なシェルスクリプトの必要性を排除します。