1개를 제외한 모든 중복 이미지 파일을 제거합니다.

1개를 제외한 모든 중복 이미지 파일을 제거합니다.

꽤 많은 중복이 포함된 이미지 폴더가 있는데 하나만 빼고 모두 제거하고 싶습니다.

인터넷 검색을 통해 이 영리한 스크립트를 찾았습니다.이 게시물간략하게 말하자면거의내가 원하는 것:

#!/bin/sh -eu
find "${1:-.}" -type f ! -empty -print0 | xargs -0 md5 -r | \
    awk '$1 in a{sub("^.{33}","");printf "%s\0",$0}a[$1]+=1{}' | \
    xargs -0 rm -v --

불행하게도 저는 UNIX 쉘 스크립팅을 처음 접했기 때문에 각 섹션의 실제 명령/플래그가 여기에서 무엇을 하는지 잘 모르기 때문에 특정 요구 사항에 맞게 수정할 수 없습니다.

내가 이해하는 한도에서는:

find "${1:-.}" -type f ! -empty -print0- 현재 디렉터리에서 비어 있지 않은 파일을 검색하고 파일 이름을 인쇄합니다. (이 노래는 무슨 "${1:-.}"뜻인지 잘 모르겠습니다 .)

| xargs -0 md5 -r- 위의 결과( xargs -0명령을 통해?)를 md5명령으로 파이프하여 각 파일의 md5 해시 서명을 얻습니다( -r출력을 반전하여 한 줄로 만드나요?)

awk '$1 in a{sub("^.{33}","");printf "%s\0",$0}a[$1]+=1{}'- 여기서 길을 잃었어요..

  • $1 in a{sub("^.{33}","")- 입력을 첫 번째 공백 문자까지 가져오고 문자열 시작 부분의 처음 33자를 null( sub("^.{33}","") 로 바꿉니다.
  • printf "%s\0"-Format은 전체 문자열을 인쇄합니다.
  • a{...,$0}- 이게 무슨 일인지 모르겠어요.
  • a[$1]+=1{}- 아직 확실하지 않음

xargs -0 rm -v ---각 파일 이름을 인쇄하여 결과를 rm명령 에 파이프하지만 구문이 무엇 인지 -v잘 모르겠습니다 .--

실행해 보면 아래와 같이 출력되는데 ./test3.jpg./test2.jpg./test.jpg: No such file or directory포맷 문제가 있는 것 같습니다.

내 질문은 다음과 같습니다

  1. 1개를 제외한 모든 파일을 삭제하도록 수정이 가능한가요?
  2. 위에서 설명한 명령/구문 의미 사이의 차이를 설명하는 데 도움을 줄 수 있는 사람이 있습니까?

UNIX에 익숙한 사람이라면 이것이 쉬울 것이라고 확신합니다. 그러나 불행하게도 그 사람은 제가 아닙니다. 미리 감사드립니다!

맥락: 저는 이것을 macOS BigSur 11의 ZSH에서 실행하고 있습니다.

답변1

awk여기서는 - 부분 에 중점을 둘 것입니다 .

md5 -r32자 md5-sum과 파일 이름을 반환합니다. 따라서 md5-sum은 awk.

$1 in a{...}

" $1(여기서: md5-sum)이 배열의 인덱스로 발견 되면 a{...} 명령을 실행하십시오"를 의미합니다. 따라서 amd5가 있는 배열과 이미 표시된 인덱스로 사용됩니다. 값이 존재하지 않거나 0이면 명령이 실행되지 않습니다. 따라서 md5-sum을 처음 볼 때 파일 이름은 다음과 같습니다.아니요뒤쪽에. 다른 값(문자열 포함)이면 조건이 true이고 명령이 실행됩니다.

sub("^.{33}","");printf "%s\0",$0

md5-sum과 다음 공백인 33자가 처음부터 제거되고 나머지(원본 파일 이름)는 끝에 NUL 구분 기호와 함께 인쇄됩니다. 공백 등이 있는 파일에는 NUL 구분이 중요합니다. 또는 를 -print0참조 하세요 . 이 명령은 md5-sum이 이미 배열에 있는 경우에만 실행되므로 첫 번째 일치 항목이 반환되지 않습니다(즉, 중복 항목만 표시되고 나중에 제거됩니다).man find-0man xargsa

a[$1]+=1{}

"배열 요소 $1 + 1 a", $1은 md5-sum입니다. 따라서 amd5-sum이 표시되면 값이 설정됩니다. 이것은 반복 카운터입니다. '{}'은(는) 빈 명령입니다. 이는 awk기본적으로 조건이 충족되고 명령이 제공되지 않으면 전체 레코드가 반환되기 때문에 필요합니다 .


경고하다

내가 아는 한 스크립트는 공백이 있는 파일에서는 잘 작동하지만 awkNUL이 레코드 구분 기호로 설정되지 않고 기본값이 newlines로 설정되기 때문에 이름에 개행 문자가 있는 파일에서는 실패한다고 생각합니다. BEGIN {RS="\x0"}먼저 in을 사용하여 awk설정하세요.

관련 정보