指定したテキストを含まないすべてのファイルを削除するにはどうすればよいですか。
指定したテキストを含むファイルを削除する解決策は理解していますが、指定したパターンを含まないファイルを削除する必要があります。
次のコマンドは、「成功した実行」を含まないファイルのリストを作成します。
grep -c "successful run" *.out | grep -v ":1" > err.txt
これらのファイルを直接削除したいです。
答え1
適切なファイルを識別するための独自のアプローチ
grep -c "successful run" *.out | grep -v ":1"
欠陥がある。主な懸念事項:
- 1 つのファイルに 2 つ以上の一致する行がある場合はどうなりますか?
grep ":0"
という質問のタイトルの条件 (「パターンを含まないファイル」) により適しているようです。 - ファイル名に
:1
(または) が含まれている場合はどうなりますか? そうすると、さらに良くなるようです。:0
grep ':0$'
- 最初に渡されたファイル名に改行文字が含まれていた場合はどうなりますか
grep
?
に頼るのではなく、行が選択されなかった場合はのgrep -c
終了ステータスに頼ることをお勧めします。grep
1
for f in *.out; do
[ -f "$f" ] && {
grep -q -- "successful run" "$f"
[ "$?" -eq 1 ] && rm -i -- "$f"
}
done
ノート:
[ -f "$f" ] && …
grep
一致するディレクトリ、fifo などでは動作せず*.out
、通常のファイルのみで動作します。- の意味と重要性
--
を説明しますここ。 で始まる名前のファイルがある場合-
、オプションと間違われる可能性があります。 この問題に対処するもう 1 つの方法は ですfor f in ./*.out; do …
。 この方法では、展開されたすべての が$f
で始まるため./
、 で始まることはできません-
。 - 念のため使用しました
rm -i
。ソリューションをテストした後は、省略することもできます-i
。 grep … || rm …
はもっと悪いです。実際のエラーが発生した場合 (例: 権限が拒否された場合)、 の終了ステータスはgrep
より大きくなります1
。その場合、ファイルを削除したくないでしょう。私の解決策は、終了ステータスが とまったく同じかどうかをテストします1
。- あなたの元のコードはサブディレクトリに降りていきません。私のコードも同様です。再帰が必要な場合は、再帰をサポートするシェル (および を使用した Bash など
shopt -s globstar
)**
または に基づくソリューションfind
が役立ちます。
答え2
ファイルに「正常に実行された」回数が 1 回か、まったく実行されなかったことを考慮すると、次のようになります。
一致するファイルを見つけるには、次の操作を実行します。
grep -l "successful run" *.out > err.txt
これらを見つけて削除するには:
grep -l "successful run" *.out | xargs rm
一致しないファイルを検索するには、次のようにします。
grep -vl "successful run" *.out > ok.txt
これらを見つけて削除するには:
grep -vl "successful run" *.out | xargs rm
旗の意味は次のとおりです:
-l lists the files with matches
-v/--invert-match inverts the matching logic