回答:
安全な方法は次のとおりです。
grep -lrIZ foo . | xargs -0 rm -f --
-l
検索パターンに一致するファイルのファイル名を出力します。-r
foo
指定されたディレクトリでパターンの再帰検索を実行し.
ます。これが機能しない場合は、を試してください-R
。-I
(capital i
)は、PDFなどのバイナリファイルをスキップします。-Z
空白を含む名前が間違った方法で解釈されないように(つまり、1つではなく複数の名前として)、ファイル名がゼロ(つまり、nul-)で終了するようにします。xargs -0
からgrep
にファイル名を送り、rm -f
単語をゼロ(nul)バイトで区切ります(-Z
からのオプションを思い出してくださいgrep
)。--
はしばしば忘れられますが、オプションの終わりをマークして、名前がで始まるファイルの削除を考慮するのは非常に重要-
です。どのファイルが削除されようとしているのかを確認したい場合は、単に| xargs -0 rm -f --
パーツを削除し、Z
オプションを省略しますgrep
。
別のユーザーから次のような提案がありましたが、安全ではないため実行しないでください。
files=`grep foo * | cut -d: -f1`
rm -f $files # unsafe, do not run it!
私はファイルを持っている場合ImportantStuff
、私は削除し、したくないことをobsolete ImportantStuff
含むfoo
、それから私を失うImportantStuff
(とない obsolete ImportantStuff
!)ので、私は、このコマンドを実行すると$files
、それが解釈されたときにスペースを空けて壊れます。この方法でファイル名のリストをスカラーシェル変数に入れることは危険です。
$ find -type f -exec grep -q "foo" {} \; -exec echo rm -- {} \;
これは、を含むファイルを再帰的に検索しますfoo
。2番目-exec
は、最初exec
が正常に終了した場合、つまりgrep
一致した場合にのみ実行されます。ドライランしecho
、出力が正しいと思われる場合は削除します。
または代わりに
$ find -type f -exec grep -q "foo" {} \; -print
そして
$ find -type f -exec grep -q "foo" {} \; -delete
Lekensteynが提案したとおり。
find -type f -exec grep -q 'foo' {} \; -delete
(引用符{}
は不要find
です。ファイルを削除することもできます)。grep
正規表現を受け入れることに注意してください。を検索する場合はfoo.bar
、これをエスケープするか-F
、パターンをリテラルとして扱うオプションを渡します。
-exec echo rm "{}" \;
はありませんか-delete
?
-delete
。2番目-exec
とエコーを配置することでデモンストレーションが簡単になります。
-print
(または-ls
より詳細に)入力する方が簡単です-exec echo rm "{}" \'
。外部ユーティリティは必要ありません。
エイドリアンが言ったことをやります
ただし、 "food"を含むファイルを誤って削除しないように、fooの周囲に単語の境界を追加します(foodを含むすべてを削除する場合を除きます)。
$ find -type f -exec grep -q "\<foo\>" {} \; -delete
実際には、削除する前に出力をリダイレクトして、削除する前に確認できるようにしました。
$ find -type f -exec grep -q "\<foo\>" > /tmp/list_of_files_to_delete