파일의 모든 줄을 반복하고 내용에 해당 줄이 포함된 모든 파일을 삭제합니다.

파일의 모든 줄을 반복하고 내용에 해당 줄이 포함된 모든 파일을 삭제합니다.

우리는 자동화하려고 하는 매우 수동적이고 기본적인 이메일 구독 취소 시스템을 가지고 있습니다. 구독을 취소할 이메일 주소 목록이 포함된 파일이 있는데, 파일은 한 줄에 하나의 이메일 주소를 갖도록 형식이 지정되어 있으므로 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.

예를 들어 이메일의 형식이 정확히 어떻게 지정되었는지 정확히 알고 있는 경우, 예를 들어 항상 다음과 같은 줄이 한 번만 포함된 경우:

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 출력에서 ​​파일 이름을 추출하여 제거합니다.

관련 정보