文字列foo
を含むすべてのファイルを削除します。 Linuxでbashを使用してこれを行うにはどうすればよいですか?
安全な方法は次のとおりです。
grep -lrIZ foo . | xargs -0 rm -f --
-l
は、検索パターンに一致するファイルのファイル名を出力します。-r
は、指定されたディレクトリ.
でパターンfoo
を再帰的に検索します。これが機能しない場合は、-R
をお試しください。-I
(大文字のi
)を使用すると、PDFなどのバイナリファイルがスキップされます。-Z
は、空白を含む名前が誤った方法で解釈されないように(つまり、1つではなく複数の名前として)、ファイル名がゼロ(つまり、nul-)で終了することを保証します。xargs -0
は、ファイル名をgrep
からrm -f
までフィードし、単語をゼロ(nul)バイトで区切ります(grep
の-Z
オプションを思い出してください)。--
はしばしば忘れられますが、オプションの終わりをマークし、名前が-
で始まるファイルの削除を許可することは非常に重要です。削除されるファイルを確認する場合は、| xargs -0 rm -f --
の部分を削除し、Z
オプションをgrep
にしないでください。
別のユーザーが次のようなものを提案しました。これは安全でないため、(実行しないでください)です。
files=`grep foo * | cut -d: -f1`
rm -f $files # unsafe, do not run it!
削除したくないファイルImportantStuff
とfoo
を含むobsolete ImportantStuff
がある場合、ImportantStuff
を失います(そしてnotobsolete ImportantStuff
!)このコマンドを実行すると、解釈されたときに$files
がスペースで分解されるためです。このようにファイル名のリストをスカラーシェル変数に入れるのは危険です。
$ find -type f -exec grep -q "foo" {} \; -exec echo rm -- {} \;
これにより、foo
を含むファイルが再帰的に検索されます。二番目 -exec
は、最初のexec
が正常に終了した場合、つまりgrep
が一致した場合にのみ実行されます。出力が正しいと思われる場合は、ドライランしてecho
を削除します。
または代わりに
$ find -type f -exec grep -q "foo" {} \; -print
そして
$ find -type f -exec grep -q "foo" {} \; -delete
lekensteynによって提案されたように。
私はエイドリアンの言うことをします、
しかし、「食品」を含むファイルを誤って削除しないように、fooの前後にWordの境界を追加します(食品を含むすべてを削除するのが目的のものでない限り)。
$ find -type f -exec grep -q "\<foo\>" {} \; -delete
実際には、削除する前に出力をリダイレクトするので、削除する前に確認できます。
$ find -type f -exec grep -q "\<foo\>" > /tmp/list_of_files_to_delete