파일 이름이 파일에 포함된 문자열과 일치하는 파일 삭제

파일 이름이 파일에 포함된 문자열과 일치하는 파일 삭제

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보다 더 강력하고 유연한 것을 사용할 수도 있습니다(예: awk또는 perl, 둘 다 NUL 구분 입력을 처리하는 데 문제가 없으며 Perl에는 파일 삭제를 위한 내장 unlink()기능도 있으므로 필요하지 않습니다 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

관련 정보