꽤 많은 중복이 포함된 이미지 폴더가 있는데 하나만 빼고 모두 제거하고 싶습니다.
인터넷 검색을 통해 이 영리한 스크립트를 찾았습니다.이 게시물간략하게 말하자면거의내가 원하는 것:
#!/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개를 제외한 모든 파일을 삭제하도록 수정이 가능한가요?
- 위에서 설명한 명령/구문 의미 사이의 차이를 설명하는 데 도움을 줄 수 있는 사람이 있습니까?
UNIX에 익숙한 사람이라면 이것이 쉬울 것이라고 확신합니다. 그러나 불행하게도 그 사람은 제가 아닙니다. 미리 감사드립니다!
맥락: 저는 이것을 macOS BigSur 11의 ZSH에서 실행하고 있습니다.
답변1
awk
여기서는 - 부분 에 중점을 둘 것입니다 .
md5 -r
32자 md5-sum과 파일 이름을 반환합니다. 따라서 md5-sum은 awk
.
$1 in a{...}
" $1
(여기서: md5-sum)이 배열의 인덱스로 발견 되면 a
{...} 명령을 실행하십시오"를 의미합니다. 따라서 a
md5가 있는 배열과 이미 표시된 인덱스로 사용됩니다. 값이 존재하지 않거나 0이면 명령이 실행되지 않습니다. 따라서 md5-sum을 처음 볼 때 파일 이름은 다음과 같습니다.아니요뒤쪽에. 다른 값(문자열 포함)이면 조건이 true이고 명령이 실행됩니다.
sub("^.{33}","");printf "%s\0",$0
md5-sum과 다음 공백인 33자가 처음부터 제거되고 나머지(원본 파일 이름)는 끝에 NUL 구분 기호와 함께 인쇄됩니다. 공백 등이 있는 파일에는 NUL 구분이 중요합니다. 또는 를 -print0
참조 하세요 . 이 명령은 md5-sum이 이미 배열에 있는 경우에만 실행되므로 첫 번째 일치 항목이 반환되지 않습니다(즉, 중복 항목만 표시되고 나중에 제거됩니다).man find
-0
man xargs
a
a[$1]+=1{}
"배열 요소 $1 + 1 a
", $1은 md5-sum입니다. 따라서 a
md5-sum이 표시되면 값이 설정됩니다. 이것은 반복 카운터입니다. '{}'은(는) 빈 명령입니다. 이는 awk
기본적으로 조건이 충족되고 명령이 제공되지 않으면 전체 레코드가 반환되기 때문에 필요합니다 .
경고하다
내가 아는 한 스크립트는 공백이 있는 파일에서는 잘 작동하지만 awk
NUL이 레코드 구분 기호로 설정되지 않고 기본값이 newlines로 설정되기 때문에 이름에 개행 문자가 있는 파일에서는 실패한다고 생각합니다. BEGIN {RS="\x0"}
먼저 in을 사용하여 awk
설정하세요.