(ディレクトリとそのサブディレクトリ内の)特定の文字列を含まないファイルを見つけて、それらのファイルを削除したいと思います。どうすればこれを行うことができますか?
7 に答える
以下が機能します。
find . -type f -print0 | xargs --null grep -Z -L 'my string' | xargs --null rm
これは、最初にfindを使用して、現在のディレクトリとサブディレクトリ内のすべてのファイルの名前を出力します。これらの名前は、通常の改行区切り文字ではなくnullターミネータで出力されます(引数od -c
の効果を確認するには、出力をパイプ処理してみてください。-print0
次に、nullで終了する入力を受け入れるよう--null
に指示するパラメーター。次に、ファイル名のリストを呼び出します。xargs
xargs
grep
の-Z
引数はの引数と同じように機能するgrep
ため、grepは結果をnullで終了します(これが、への最後の呼び出しにもオプションが必要な理由です)。正規表現と一致しないコマンドライン(追加済み)にこれらのファイルのファイル名を出力させる引数:-print0
find
xargs
--null
-L
grep
grep
xargs
私の文字列
正規表現の魔法を使わずに単純なマッチングが必要な場合は、-F
オプションを追加してください。より強力な正規表現が必要な場合は、-E
引数を指定してください。文字列に適用されるシェルマジック(変数の置換など)から保護するため、二重引用符ではなく一重引用符を使用することをお勧めします。
最後に、xargs
もう一度呼び出して、前の呼び出しで見つけたすべてのファイルを削除します。
引数を指定してコマンドgrep
から直接呼び出す場合の問題は、ファイルのバッチ全体に対して1回ではなく、ファイルごとに1回呼び出されることです。たくさんのファイルがある場合、これははるかに高速です。また、次のようなことをしたくはありません。find
-exec
grep
xargs
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つのダッシュで複数文字の引数が導入されていることにも注意してください。これは歴史的な理由によるものであり、スクリプトが多すぎるために修正されていません。
GNUgrepとbash。
grep -rLZ "$str" . | while IFS= read -rd '' x; do rm "$x"; done
find
移植性が必要な場合は、ソリューションを使用してください。これは少し速いです。
編集:これは、これを行うべきではない方法です! ここに理由を記します。それを指摘してくれた@ormaajに感謝します!
find . -type f | grep -v "exclude string" | xargs rm
注:grep
パターンは、現在のディレクトリからの完全なファイル パスと一致します (find . -type f
出力を参照) 。
1つの可能性は
find . -type f '!' -exec grep -q "my string" {} \; -exec echo rm {} \;
echo
このプレビューの出力が正しく見える場合は、を削除できます。
と同等のもの-delete
は
find . -type f '!' -exec grep -q "user_id" {} \; -delete
しかし、その後、素晴らしいプレビューオプションが得られません。
これにアプローチするいくつかの方法を考えることができます。これが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」を使用してテストすることをお勧めします。