![特定のコンテンツを含むファイルを削除する](https://rvso.com/image/178487/%E7%89%B9%E5%AE%9A%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%E3%82%92%E5%90%AB%E3%82%80%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%89%8A%E9%99%A4%E3%81%99%E3%82%8B.png)
ディレクトリ内に何千ものデータ ファイル (同じ拡張子) がある場合、特定のパラメーター ステートメントを含むデータ ファイルを削除するにはどうすればよいでしょうか。
例えば、次の行を含むすべてのファイルを削除しようとした場合、
Key = 0
こんなことをしてもいいかな
grep -i "Key = 0" * | rm *
答え1
シェルで次のコマンドを使用できます。検索するパターンがKey = 0
grep -lrIZ "Key = 0" . | xargs -0 rm -f --
汎用コマンド:
grep -lrIZ "<Pattern to be searched in the file>" . | xargs -0 rm -f --
答え2
grep
+を使用するパイプラインの主な問題は、標準入力ストリームから読み取らないことrm
ですrm
。つまり、grep
パイプの左側のコマンドからは何も読み取られません。
代わりに、rm *
パイプの右側ではすべての入力が無視され、rm
現在のディレクトリ内のすべての表示ファイル名に対して実行されます。
rm
標準入力を読み取らないという問題を無視すると、grep
コマンドには主に 2 つの問題があります。
rm
一致する行をファイル名とともに出力します。これは、必要な情報ではないので、のみ削除したいファイルのファイル名。- それ
Key = 0
は、部分文字列つまり、Crypto Key = 0x01
などとも一致します。
find . -type f -exec grep -q -F -x 'Key = 0' {} \; -exec rm -f {} +
あるいは、GNU find
(および他のもの)では、
find . -type f -exec grep -q -F -x 'Key = 0' {} \; -delete
どちらも現在のディレクトリまたはその下にある通常のファイルを検索し、見つかったファイルごとにを実行しますgrep -q -F -x 'Key = 0'
。このgrep
コマンドは、ファイル内に次の行があるかどうかを示す終了ステータスを返します。その通り Key = 0
(何もありません)。
2 番目のコマンドは、そのような行が見つかった場合に述語find
を使用してファイルを削除します。最初のコマンドは、この行を含むファイルのパス名を収集し、それらのバッチに対して実行します。-delete
find
rm -f
使用されるフラグgrep
は
-q
、静かな操作用。ユーティリティは一致する行を出力しませんが、最初の一致の後に正常に終了するか、ファイルに一致するものが含まれていない場合は 0 以外の終了ステータスで終了します。-F
固定文字列マッチングの場合。正規表現ではなく文字列でマッチングします。-x
, は、行全体の一致のみを検索します。これは、行の先頭と末尾の両方に固定された正規表現を使用する場合と同じ効果があります。
-i
ここでwith は使用していません。これは、 andなどgrep
の行を含むファイルも削除してしまうためです。また、これらの大文字と小文字の違いについては何も言及されていません。KEY = 0
kEY = 0
find
コマンドを のような特定のファイル名サフィックスに制限したい場合は.ext
、の実行前に コマンド-name '*.ext'
で を使用します。例:find
grep
find . -name '*.ext' -type f -exec grep -q -F -x 'Key = 0' {} \; -exec rm -f {} +