ファイル内のすべての行を繰り返し、内容にその行を含むすべてのファイルを削除します。

ファイル内のすべての行を繰り返し、内容にその行を含むすべてのファイルを削除します。

自動化しようとしている非常に受動的で基本的な電子メール購読キャンセルシステムがあります。サブスクリプションをキャンセルする電子メールアドレスのリストを含むファイルがあり、ファイルは1行に1つの電子メールアドレスを持つようにフォーマットされているため、catを使用すると機能するようです。

同じフォルダには、sendmailに一括送信された何千もの「.eml」ファイル(生の電子メールファイル)があります。これらの.emlファイルを作成するのは費用がかかるので、そのファイルをフォルダに保存し、誰かが購読をキャンセルするまで定期的に送信します。私が望むのは、ファイル内のすべての電子メールアドレスを繰り返し、各電子メールアドレスのフォルダからgrepを実行してから、grepに一致するファイルを削除するbashスクリプトを書くことです。

私のUnixテクノロジは非常に限られているので、Unixテクノロジを向上させるためにこれを再利用可能なbashスクリプト(ループなどを含む)にしようとしています。

答え1

簡単な方法は次のとおりです(GNUユーティリティを想定)。

grep -FZlw -f address.list -- *.eml | xargs -r0 rm -f --

または同じですが、GNUユーティリティでサポートされている長いオプションがあります。

grep --fixed-strings \
     --null --files-with-matches \
     --word-regexp \
     --file address.list \
     -- *.eml |
 xargs --no-run-if-empty --null \
   rm --force --

ただし、アドレスが見つかるとファイルは削除されます。どこかにファイルのFrom:、、、、ヘッダー、または電子メールの本文または添付ファイルにありますTo:Cc:Reply-To

また、から送信された電子メールもaddress.list含まれている場合は[email protected]削除されます。[email protected][email protected]

address.listまた、ファイルの電子メールアドレスが同じ形式(同じ場合はMIMEエンコードなし)であると仮定しますeml

たとえば、電子メールの形式が正確にどのように指定されたかを正確に知っている場合、たとえば常に次の行が1回だけ含まれている場合:

To: [email protected]

[email protected]書式があなたの書式とまったく同じ場合は、address.list次のことができます。

sed 's/^/To: /' address.list | grep -xZFlf - -- *.eml | xargs -r0 rm -f --

どちらがより信頼できますか?

address.listリストに渡す代わりに性格ファイルの任意の場所を見つけるには、まずsstream editorコマンドを使用して検索リストを変換し、各行にプレフィックスを追加します"To: "固定文字列パターンが変更され、/ の代わりに / を使用して行 e の内容全体と一致します。 (たとえば一致しません)。To: [email protected]-x--line-regexp-w--word-regexpxTo: [email protected]Reply-To: [email protected].eu

ファイルを削除したくないが削除したいファイルのヘッダーを確認したい場合は、rm -f上記のように置き換えてください。grep -H '^To:'To:

答え2

次のスクリプトを使用します。

#!/bin/bash

email_dir=./emails
unsubscribe_file=./emails/unsubscribe.txt

while IFS= read -r email _; do
    files=($(grep -rni "$email" "$email_dir" | grep -v 'unsubscribe.txt'))
    if ((${#files[@]}>1)); then
        printf '%s\n' "warning: Found multiple files for: $email" "${files[@]}" >&2
    elif ((${#files[@]}==1)); then
        rm "$(echo "${files[0]}" | awk -F\: '{print $1}')"
    fi
done < "$unsubscribe_file"

email_dir電子メールを含むディレクトリパスは、 unsubscribe_file購読をキャンセルする電子メールを含むファイルパスに設定する必要があります。

whileループはサブスクリプションキャンセルファイルを読み取り、各行の最初のフィールドにemail変数を設定します(このフィールドは唯一のフィールドである必要がありますが、残りのフィールドは存在する_場合はキャプチャされます)。

その電子メールアドレスのディレクトリ内のすべてのファイルに対してgrepを実行しますemail_dir。これにより、購読解除ファイルも返されるため、grepを使用して結果からそのファイルを削除します。同じディレクトリにない場合は理想的です。 grep -v 'unsubscribe.txt'ただし、購読をキャンセルしたファイルの実際の名前を反映するように変更する必要があります。)

結果が複数ある場合に備えて、これらの結果を配列に設定します。この場合、エラーが発生し、何も削除されません。結果が1つだけの場合は、grep出力からファイル名を抽出して削除します。

関連情報