셸 스 크 립 트 는 폴 더 에서 중복 되 는 파일 을 찾 고 삭제 기능 을 제공 합 니 다.

5883 단어 Linux
Windows 에 소프트웨어 FindDupfile 이 있 습 니 다. 지정 한 디 렉 터 리 와 하위 디 렉 터 리 를 검색 하여 모든 내용 이 똑 같은 파일 (파일 이름 이 다 를 수 있 음) 을 표시 한 다음 사용자 가 중복 되 는 파일 을 삭제 하 는 것 을 선택 할 수 있 습 니 다.
그러나 셸 스 크 립 트 는 몇 줄 의 명령 을 사용 하여 이와 같은 작업 을 수행 할 수 있 습 니 다. windows 의 셸 스 크 립 트 도구 인 Cygwin 을 통 해 Windows 의 디 렉 터 리 를 스 캔 할 수 있 습 니 다. 원 리 는 다음 과 같 습 니 다.
1. 우선 find 명령 을 통 해 폴 더 의 다음 형식 이 일반 파일 인 모든 파일 을 검색 합 니 다. find 명령 의 출력 은 한 줄 의 파일 입 니 다.
2. find 에서 찾 은 모든 파일 에 대해 MD5 검 사 를 실시 합 니 다. 검사 명령 은 md5sum files 이 고 출력 텍스트 형식 은 MD5SUM 입 니 다. *file
3. 내용 의 파일 의 md5 검사 값 은 같 습 니 다. 모든 MD5SUM 검사 값 을 같은 값 으로 조회 하기 때문에 awk 의 관련 배열 을 사용 하여 다른 파일 을 출력 합 니 다.
4. awk 출력 중 복 된 파일 시트 를 삭제 합 니 다.
셸 스 크 립 트 는 다음 과 같 습 니 다:
#!/bin/bash -

#查找文件夹下相同的文件
#Usage: dupfile.sh [-ds] dirs
#       dirs 请用单引号引起来

del=0
silent=0

trap "" PIPE

#参数处理
while test $# -gt 0
do
	case $1 in
		-d | --delete) 
			del=1
			;;
		-s | --silent)
			silent=1
			;;
		-*)	
			break
			;;
		*)	
			break
			;;
	esac
	shift
done

if [ $# -eq 0 ]
then
	echo "Usage: dupfile.sh [-ds] dirs" >&2
	exit 0
fi

#find查找所有文件并进行MD5校验,
# md5sum对二进制文件输出为 MD5SUM *file
#  awk使用关联数组处理相同的md5值并按照格式输出,使用DEL传递参数
#   tee命令将管道拷贝一份到进程替换,另一份到stdout
find "$@" -type f -exec md5sum {} + |  
	awk -v FS="*" -v DEL=$del -v SLT=$silent '
		{
			if($1 in md5)
				md5[$1] = md5[$1] "*" $2
			else
				md5[$1] = $2
		}
		END{
			for(key in md5)
			{
				if(DEL==0) K++
				n = split(md5[key], files, "*")
				if(SLT==1 && n==1) continue
				if(DEL==0)
					printf("%-*s  %s
", length(key), key, files[n]) for(n-- ;n>0 ; n--) { K++ if(DEL==0) printf("%-*s %s
", length(key), "", files[n]) else printf("\"%s\"
", files[n]) } } K = K>0 ? K : 0 print "Total: " K " files" }' | tee >( if [ "$del" -eq 1 ] then xargs rm -f else tee >/dev/null fi )

 
Cygwin 으로 Windows 에서 테스트 한 결 과 를 보십시오. (열 거 된 모든 디 렉 터 리 에 따옴표 추가 에 주의 하 십시오)
 우선, 저 는 E 판 test 디 렉 터 리 에 10 개의 임시 파일 을 만 들 었 습 니 다. 파일 이 모두 비어 있 습 니 다. 테스트 결 과 는 다음 과 같 습 니 다.
hp@hp-PC ~
$ (cd 'E:/test'; i=0; while [ "$i" -lt 10 ] ; do mktemp "./XXXXXX" ; i=$((i+1)) ; done)
./pOsdFm
./5tndDZ
./wjSDR2
./oFrSaG
./7zlZcA
./9sNmEo
./UVDQLR
./qZdDNI
./iwfYdn
./IP52BK

hp@hp-PC ~
$ ./dupfile.sh 'E:/test'
cygwin warning:
  MS-DOS style path detected: E:/test
  Preferred POSIX equivalent is: /cygdrive/e/test
  CYGWIN environment variable option "nodosfilewarning" turns off this warning.
  Consult the user's guide for more details about POSIX paths:
    http://cygwin.com/cygwin-ug-net/using.html#using-pathnames
d41d8cd98f00b204e9800998ecf8427e   E:/test/wjSDR2
                                   E:/test/UVDQLR
                                   E:/test/qZdDNI
                                   E:/test/pOsdFm
                                   E:/test/oFrSaG
                                   E:/test/iwfYdn
                                   E:/test/IP52BK
                                   E:/test/9sNmEo
                                   E:/test/7zlZcA
                                   E:/test/5tndDZ
Total: 10 files

hp@hp-PC ~
$

그 결과 중 복 된 빈 파일 10 개 를 완전히 찾 아 냈 다.
- d 옵션 을 사용 하면 중 복 된 것 을 삭제 하고 그 중 하나 만 유지 할 수 있 습 니 다.
hp@hp-PC ~
$ (cd 'E:/test' ; ls ;)
5tndDZ  7zlZcA  9sNmEo  IP52BK  iwfYdn  oFrSaG  pOsdFm  qZdDNI  UVDQLR  wjSDR2

hp@hp-PC ~
$ ./dupfile.sh -d 'E:/test'
"E:/test/UVDQLR"
"E:/test/qZdDNI"
"E:/test/pOsdFm"
"E:/test/oFrSaG"
"E:/test/iwfYdn"
"E:/test/IP52BK"
"E:/test/9sNmEo"
"E:/test/7zlZcA"
"E:/test/5tndDZ"
Total: 9 files

hp@hp-PC ~
$ (cd 'E:/test' ; ls ;)
wjSDR2

다른 상황 을 다시 한 번 테스트 해 보 겠 습 니 다. 저 는 E:/test 디 렉 터 리 에서 10 개의 다른 파일 을 만 들 었 습 니 다. 각 파일 에는 자신의 파일 이름 이 포함 되 어 있 습 니 다.
hp@hp-PC ~
$ (cd 'E:/test'; i=0; while [ "$i" -lt 10 ] ; do name=`mktemp "./XXXXXX"` ; echo "$name" > "$name" ; i=$((i+1)) ; done)

hp@hp-PC ~
$ ./dupfile.sh 'E:/test'
26288eeea00c650ae612dcf5b0efa5ab   E:/test/wBMk5c
6f28a86738b227553b116914befd7b55   E:/test/lOT1Yd
1bc7d2563796cf63c7f0d68affb190ef   E:/test/haDFBY
679bc5d2d3e17761185ed82d43fd7d4a   E:/test/CHOmSd
aaefa81fafd87bf3c3378ef02e22ef5a   E:/test/yZ635B
e13b59ae07a9fd0e0a8095701c4003b2   E:/test/QdWtsN
ae2eabc1232111d9f12190b3a62d60bf   E:/test/13PWOU
621d060c7c313f06eff1ce21a6b25f0c   E:/test/sql7KV
7108830bbf019166d4af9a10030384f3   E:/test/lxGd5y
6dc2d2815a69f8a754503f1301e1cbcb   E:/test/efUo7c
Total: 10 files

보 이 는 것 은 모두 다른 파일 입 니 다. 파일 수가 많 을 때 - s 옵션 을 사용 하여 조용히 출력 할 수 있 습 니 다. 중복 되 는 파일 만 표시 하고 중복 되 지 않 는 파일 은 표시 되 지 않 습 니 다.
 
마지막 으로 흥미 로 운 문제 가 있 습 니 다. 테스트 에서 dupfile 프로그램의 마지막 파이프 끝의 tee > (...) 명령 이 영문 도 모 르 게 종 료 됩 니 다. 스 크 립 트 의 종료 코드 는 141 이 고 SIGPIPE 신호 에 대응 합 니 다.
나의 원래 대본 은 마지막 에 이렇게 썼 다.
			tee >(
					if [ "$del" -eq 1 ]
					then
						xargs rm -f
					fi
				 )

분석 결과, > (...) 와 같은 프로 세 스 교체 의 실현 원 리 는 이름 파 이 프 를 통 해 이 루어 집 니 다. 먼저 > (...) 이 위 치 를/dev/fd/63 또는 다른 이름 파이프 파일 로 바 꾼 다음 에 새로운 bash 프로그램 을 시작 하여 > (...) 의 명령 부분 을 실행 하고 bash 프로그램의 표준 입력 은/dev/fd/63 의 파이프 출력 단 으로 대 체 됩 니 다.이때, 왜 SIGPIPE 신 호 를 촉발 합 니까?
괄호 내부 의 명령 부분 은 판단 문 입 니 다. 부정 으로 판 단 될 때 xargs 명령 이 실행 되 지 않 기 때문에 시 작 된 bash 프로그램 이 종 료 됩 니 다. 이때 tee 명령 이/dev/fd/63 이 파이프 에 쓸 때 SIGPIPE 신 호 를 받 습 니 다. 시 작 된 bash 프로그램 이 종료 되 지 않도록 하 는 방법 입 니 다. else 문 구 를 추가 합 니 다. tee >/dev/null.아니면 SIGIPE 신 호 를 무시 하고 trap ""SIGIPE "를 추가 하면 됩 니 다. 동시에 tee 명령 의 stderr 출력 을 tee 2 >/dev/null 무시 합 니 다.  > ( ... ).
 
 

좋은 웹페이지 즐겨찾기