ファイル名がファイルに含まれる文字列と一致するファイルの削除

ファイル名がファイルに含まれる文字列と一致するファイルの削除

del.txtランダムに生成された識別文字列のリストを含むテキストファイルがあります。たとえば、次のようになります。

07ckv978yk0
HuinLBoZHcY
_oR7ccXiunY

ファイル名に識別文字列を含むすべてのファイルを削除したいです。ファイル名20191223_abcdef_07ckv978yk0.jsonは、必ずしも.jsonである必要はないファイル拡張子の直前、ファイル名の末尾に一致する文字列を見つけることができる形式です。各文字列に一致する複数のファイルを持つことはできますが、ファイルに一致する複数の文字列を持つことはできません。

似たようなことを試してみましたが、うまくいくようfind . -type f -name "*" -exec grep -Flf ~/del.txt '{}' \; -printですが、非常に長い時間がかかりました(一致する文字列が2000個で、確認する必要があるファイル名がはるかに多い)。拡張子を指定して作業をスピードアップできますが、ファイル拡張子はさまざまなので、これを行うより賢い方法があることを願っています。

答え1

find コマンドを作成する方法は次のとおりです。

  1. grep各ファイル名に対して一度実行
  2. ナビゲーションコンテンツファイルではなくファイル別名前それ自体。

これは非常に遅く、実際にやりたいことをすることはできません。

次のことをさらに試してください。

find . -type f | grep -Ff ~/del.txt

grepは一度だけ実行され、ファイルの内容ではなくファイル名をgrepします。

削除するファイルのリストを作成するのではなく、一致するファイルを同時に削除するには、次の手順を実行します。

find . -type f -print0 | grep -z -Ff ~/del.txt | xargs -0r rm

ファイル名(パス/ファイル名には現れない唯一の文字)の間の区切り文字としてNULを使用するため、スペース、改行、およびシェルメタ文字のファイル名を含むファイル名など、すべてのファイル名に安全に使用できます。


del.txt上記の両方のバージョンは、ファイル名に表示される固定文字列と一致します。ファイル名の特定の場所でのみ一致させるには、固定文字列の代わりに正規表現を使用する必要があります。あるいは、一致を実行するためにgrepよりも強力で柔軟なものを使用することもできます(たとえば、どちらもNUL区切り入力を処理するのに問題がなく、Perlにはファイルを削除するための組み込みawk機能もあるため必要ありません)。perlunlink()xargs

ファイル名 "extension" (リテラル文字) の前にのみ一致するパターンなどの単純なものが必要な場合は、各固定文字列が次のように始まるように変更できます.del.txt.

ファイルを手動で編集するか、次を使用できます。プロセスの交換sedすぐに修正してください。たとえば、

find . -type f -print0 |
  grep -z -Ff <(sed -E -e 's/([^.])$/\1./' del.txt) |
  xargs -0r rm

このsedコマンドは、.で終わらないすべての行にを追加します.。それ自体は変更されず、del.txtストリームコピーのみが変更され、grepのオプションで使用されます-f

答え2

存在するzsh

blacklist=( ${(f)"$(<del.txt)"} )
print -rC1 -- **/*(${(~j[|])blacklist}).*(D.)

投稿rに印刷してください。1 C削除するにprint -rC1はに置き換えますrm -f

または一時的な配列なしで:

print -rC1 -- **/*(${(~j[|])${(f)"$(<del.txt)"}}).*(D.)
  • "$(<del.txt)"kshと同様に、ファイルの内容から末尾の改行文字を引いた内容に展開されます。
  • パラメータf拡張フラグはf行eed文字(省略形)に分割されるため、ps[\n]$blacklist要素が空でない行の内容である配列ですdel.txt
  • j[|]要素をリンクするために使用されます|。の場合、リテラルではなくグローバル演算子として扱われます~|だから私たちはグローバルパターンで終わります**/*(07ckv978yk0|HuinLBoZHcY|_oR7ccXiunY).*
  • **/すべてのレベルのサブディレクトリ。
  • DD: otfiles (隠しファイル) も含みます。
  • .: 限定定期的な文書

答え3

削除するファイルが何千ものない場合:

rm `sed 's/^/*/;s/$/.*/' del.txt`

その後、ファイルの各行を取得して次に変換します。sedこのようなグローバルモードに切り替えて*idstring.*コマンドラインに入力します。RM取り除く

にID文字列が多すぎると、del.txtコマンドラインがシェルで許可するには長すぎる可能性があります。

まず、削除されたアイテムを表示するには交換してください。RMそしてエルエス

注:これは以下には適用されません。扱いにくい私が設定した方法(あなたは評価する)、しかしそれは働く強く打つそしてシェン。スペースやその他のシェルメタ文字を含むファイル名も処理しました。これは私を驚かせました。

一致するID文字列を含むファイルが削除されると、エラーメッセージが表示されます。rm -f代替を使用するか、リダイレクトを使用する2>/dev/nullか、削除コマンドの後に削除します。del.txt

関連情報