스크립트에 몇 가지 문제가 있습니다.
먼저, 명령 결과 를 변수 에 할당하려면 변수를 백틱 ( `command`
) 또는 가급적으로 묶어야합니다 $(command)
. 'command'
명령 결과를 변수에 할당하는 대신 명령 자체를 문자열로 할당하는 작은 따옴표 ( )로 표시됩니다. 따라서 귀하 test
는 실제로 다음과 같습니다.
$ echo "test $sum1=$sum2"
test find $i -type f -iname "*.jpg" -exec md5sum {} \;=find $j -type f -iname "*.jpg" -exec md5sum {} \;
다음 문제는 명령 md5sum
이 해시 그 이상을 반환 한다는 것입니다.
$ md5sum /etc/fstab
46f065563c9e88143fa6fb4d3e42a252 /etc/fstab
첫 번째 필드 만 비교하려면 첫 번째 필드 md5sum
만 인쇄하는 명령을 통해 출력을 구문 분석해야 합니다.
find $i -type f -iname "*.png" -exec md5sum '{}' \; | cut -f 1 -d ' '
또는
find $i -type f -iname "*.png" -exec md5sum '{}' \; | awk '{print $1}'
또한이 find
명령은 하나가 아니라 많은 일치 항목을 반환하며 해당 일치 항목은 각각 두 번째에 의해 복제됩니다 find
. 어떤 시점에서 당신은 자신에게 같은 파일을 비교된다는 것을이 수단, md5sum이 동일합니다 당신이 삭제 끝날 모든 파일을 (나는이 포함 된 테스트 디렉토리에서이 작업을 실행 a.jpg
하고 b.jpg
) :
for i in $(find . -iname "*.jpg"); do
for j in $(find . -iname "*.jpg"); do
echo "i is: $i and j is: $j"
done
done
i is: ./a.jpg and j is: ./a.jpg ## BAD, will delete a.jpg
i is: ./a.jpg and j is: ./b.jpg
i is: ./b.jpg and j is: ./a.jpg
i is: ./b.jpg and j is: ./b.jpg ## BAD will delete b.jpg
for i in directory_path
디렉토리 배열을 전달하지 않으면 실행하고 싶지 않습니다 . 이러한 파일이 모두 같은 디렉토리에 있으면 for i in $(find directory_path -iname "*.jpg"
)를 실행 하여 모든 파일을 살펴 봅니다.
이다 나쁜 생각 사용하는 for
발견의 출력과 루프를. while
루프 또는 globbing을 사용해야합니다 .
find . -iname "*.jpg" | while read i; do [...] ; done
또는 모든 파일이 동일한 디렉토리에있는 경우 :
for i in *jpg; do [...]; done
쉘과 설정 한 옵션에 따라 서브 디렉토리에있는 파일에 대해서도 글 로빙을 사용할 수 있지만 여기서는 다루지 않습니다.
마지막으로 변수를 인용해야합니다. 그렇지 않으면 공백이있는 디렉토리 경로가 스크립트를 손상시킵니다.
파일 이름에는 공백, 줄 바꿈, 백 슬래시 및 기타 이상한 문자가 포함될 수 있으므로 while
루프 에서 올바르게 처리 하려면 옵션을 추가해야합니다. 당신이 쓰고 싶은 것은 다음과 같습니다.
find dir_path -type f -iname "*.jpg" -print0 | while IFS= read -r -d '' i; do
find dir_path -type f -iname "*.jpg" -print0 | while IFS= read -r -d '' j; do
if [ "$i" != "$j" ]
then
sum1=$(md5sum "$i" | cut -f 1 -d ' ' )
sum2=$(md5sum "$j" | cut -f 1 -d ' ' )
[ "$sum1" = "$sum2" ] && rm "$j"
fi
done
done
더 간단한 방법은 다음과 같습니다.
find directory_path -name "*.jpg" -exec md5sum '{}' + |
perl -ane '$k{$F[0]}++; system("rm $F[1]") if $k{$F[0]}>1'
파일 이름의 공백을 처리 할 수있는 더 나은 버전 :
find directory_path -name "*.jpg" -exec md5sum '{}' + |
perl -ane '$k{$F[0]}++; system("rm \"@F[1 .. $#F]\"") if $k{$F[0]}>1'
이 작은 Perl 스크립트는 find
명령 결과 (즉, md5sum 및 파일 이름)를 통해 실행됩니다 . -a
에 대한 옵션 perl
공백에서 분할 입력 라인과은에 저장합니다 F
그래서 배열 $F[0]
md5sum이 될 것 $F[1]
파일 이름. md5sum은 해시에 저장되며 k
스크립트는 해시가 이미 표시되었는지 확인하고 ( if $k{$F[0]}>1
) 파일이 있으면 ( ) 삭제합니다 system("rm $F[1]")
.
작동하지만 큰 이미지 모음의 경우 속도가 매우 느리므로 보관할 파일을 선택할 수 없습니다. 보다 우아한 방식으로이를 처리하는 많은 프로그램이 있습니다.