17

(ディレクトリとそのサブディレクトリ内の)特定の文字列を含まないファイルを見つけて、それらのファイルを削除したいと思います。どうすればこれを行うことができますか?

4

7 に答える 7

15

以下が機能します。

find . -type f -print0 | xargs --null grep -Z -L 'my string' | xargs --null rm

これは、最初にfindを使用して、現在のディレクトリとサブディレクトリ内のすべてのファイルの名前を出力します。これらの名前は、通常の改行区切り文字ではなくnullターミネータで出力されます(引数od -cの効果を確認するには、出力をパイプ処理してみてください。-print0

次に、nullで終了する入力を受け入れるよう--nullに指示するパラメーター。次に、ファイル名のリストを呼び出します。xargsxargsgrep

-Z引数はの引数と同じように機能するgrepため、grepは結果をnullで終了します(これが、への最後の呼び出しにもオプションが必要な理由です)。正規表現と一致しないコマンドライン(追加済み)にこれらのファイルのファイル名を出力させる引数:-print0findxargs--null-Lgrepgrepxargs

私の文字列

正規表現の魔法を使わずに単純なマッチングが必要な場合は、-Fオプションを追加してください。より強力な正規表現が必要な場合は、-E引数を指定してください。文字列に適用されるシェルマジック(変数の置換など)から保護するため、二重引用符ではなく一重引用符を使用することをお勧めします。

最後に、xargsもう一度呼び出して、前の呼び出しで見つけたすべてのファイルを削除します。

引数を指定してコマンドgrepから直接呼び出す場合の問題は、ファイルのバッチ全体に対して1回ではなく、ファイルごとに1回呼び出されることです。たくさんのファイルがある場合、これははるかに高速です。また、次のようなことをしたくはありません。find-execgrepxargs

rm $(some command that produces lots of filenames)

これはコマンドラインの最大制限を認識しており、可能な限り多くの引数を使用して毎回複数回xargs呼び出すため、これを渡すことをお勧めします。rm

このソリューションは、空白や新しい行を含むファイルを処理する必要がなければ、より単純であることに注意してください。

あるいは

grep -r -L -Z 'my string' . | xargs --null rm

動作します(そしてより短いです)。ディレクトリ内のすべてのファイルを読み取り、任意のサブディレクトリに再帰的に下降させるための-r引数)。ファイルに対して他のテスト(経過時間やアクセス許可など)も実行する場合は、このアプローチgrepを使用してください。find ...

ダッシュイントロデューサーが1つある、任意の1文字の引数をグループ化できることに注意してください(たとえば、として-rLZ)。ただしfind、同じ規則を使用しておらず、1つのダッシュで複数文字の引数が導入されていることにも注意してください。これは歴史的な理由によるものであり、スクリプトが多すぎるために修正されていません。

于 2012-07-01T15:46:45.013 に答える
5

GNUgrepとbash。

grep -rLZ "$str" . | while IFS= read -rd '' x; do rm "$x"; done

find移植性が必要な場合は、ソリューションを使用してください。これは少し速いです。

于 2012-07-01T08:11:17.663 に答える
4

編集:これは、これを行うべきではない方法です! ここに理由を記します。それを指摘してくれた@ormaajに感謝します!

find . -type f | grep -v "exclude string" | xargs rm

注:grepパターンは、現在のディレクトリからの完全なファイル パスと一致します (find . -type f出力を参照) 。

于 2012-07-01T08:02:39.520 に答える
3

1つの可能性は

find . -type f '!' -exec grep -q "my string" {} \; -exec echo rm {} \;

echoこのプレビューの出力が正しく見える場合は、を削除できます。

と同等のもの-delete

find . -type f '!' -exec grep -q "user_id" {} \; -delete

しかし、その後、素晴らしいプレビューオプションが得られません。

于 2012-07-01T08:00:16.040 に答える
1

これにアプローチするいくつかの方法を考えることができます。これが1つです。検索してgrepを実行し、一致しないファイルのリストを生成してから、xargsでそれらをrmします。

find yourdir -type f -exec grep -F -L 'yourstring' '{}' + | xargs -d '\n' rm

これは、GNUツール(grep-Lおよびxargs-dは移植性がない)であり、もちろん改行を含むファイル名がないことを前提としています。ファイルごとに1回grepとrmを実行しないという利点があるため、かなり高速になります。破壊を解き放つ前に、正しいファイルが選択されることを確認するために、「rm」の代わりに「echo」を使用してテストすることをお勧めします。

于 2012-07-01T08:18:38.800 に答える