循环遍历文件中的所有行并删除内容中包含该行的所有文件

循环遍历文件中的所有行并删除内容中包含该行的所有文件

我们有一个非常手动和基本的电子邮件取消订阅系统,我正在尝试将其自动化。有一个文件包含要取消订阅的电子邮件地址列表,该文件的格式是每行有一个电子邮件地址,因此我猜应该可以使用 cat 。

在同一个文件夹中,有数千个“.eml”文件(原始电子邮件文件)批量发送到sendmail。生成这些 .eml 文件的成本很高,因此我们将它们保存在一个文件夹中并定期发送,直到有人取消订阅。我想做的是编写一个 bash 脚本,循环遍历文件中的所有电子邮件地址,在每个电子邮件地址的文件夹上运行 grep,然后删除 grep 匹配的文件。

由于我的 Unix 技能非常有限,我正在尝试将其作为可重用的 bash 脚本(带有循环等),以便提高我的 Unix 技能

答案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

如果您确切地知道电子邮件的格式,例如,如果它们总是包含一次且仅一次出现这样的行:

To: [email protected]

其中[email protected]格式与您的完全相同address.list,那么您可以执行以下操作:

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

哪个会更可靠。

而不是将address.list作为列表传递为了在文件中的任何位置找到,我们首先使用stream 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 输出中提取文件名并将其删除。

相关内容