md5sum 프로그램은 디렉토리에 대한 체크섬을 제공하지 않습니다. 하위 디렉토리의 파일을 포함하여 디렉토리의 전체 내용에 대한 단일 MD5 체크섬을 얻고 싶습니다. 즉, 모든 파일로 구성된 하나의 결합 된 체크섬입니다. 이것을 할 수있는 방법이 있습니까?
답변
올바른 방법은 요구하는 이유에 따라 다릅니다.
옵션 1 : 데이터 만 비교
트리의 파일 내용에 대한 해시가 필요한 경우 다음과 같은 트릭을 수행합니다.
$ find -s somedir -type f -exec md5sum {} \; | md5sum
먼저 모든 파일 내용을 예측 가능한 순서로 개별적으로 요약 한 다음 해당 파일 이름 목록과 MD5 해시를 해시 자체로 전달하여 트리에있는 파일 중 하나의 내용이 변경 될 때만 변경되는 단일 값을 제공합니다.
불행히도 find -s
macOS, FreeBSD, NetBSD 및 OpenBSD에서 사용되는 BSD find (1)에서만 작동합니다. GNU 또는 SUS find (1)가있는 시스템에서 비슷한 것을 얻으려면 조금 더 추한 것이 필요합니다.
$ find somedir -type f -exec md5sum {} \; | sort -k 2 | md5sum
find -s
에 대한 통화로 교체 되었습니다 sort
. 이 -k 2
비트는 MD5 해시를 건너 뛰도록 지시하므로 필드 2에서 줄 끝까지의 파일 이름 만 계산하여 정렬합니다 sort
.
이 버전의 명령에는 약점이 있습니다. 즉, 줄 바꿈이 포함 된 파일 이름이 있으면 여러 줄로 표시되므로 혼동 될 수 있습니다 sort
. find -s
트리 탐색 및 정렬이 같은 프로그램 내에서 발생하기 때문에 변형, 그 문제를 가지고 있지 않습니다 find
.
두 경우 모두 오탐 (false positive)을 피하기 위해 정렬이 필요합니다. 가장 일반적인 Unix / Linux 파일 시스템은 디렉토리 목록을 안정적이고 예측 가능한 순서로 유지하지 않습니다. ls
디렉토리 내용을 자동으로 정렬하는 등의 사용을 인식하지 못할 수 있습니다 . find
없이 -s
또는 sort
호출은 파일의 순서는 입력의 변화로 주어진 경우이 명령이 변경된 해시 값을 제공하게되는, 기본 파일 시스템을 반환 어떤 순서로 파일을 인쇄 할 것입니다.
md5sum
명령 md5
또는 다른 해시 함수로 명령 을 변경해야 할 수도 있습니다 . 다른 해시 함수를 선택하고 시스템에 대한 두 번째 형식의 명령이 필요한 경우 sort
그에 따라 명령 을 조정해야 할 수도 있습니다 . 또 다른 함정은 일부 데이터 합산 프로그램이 파일 이름을 전혀 쓰지 않는다는 것입니다. 예를 들어 구 유닉스 sum
프로그램 이 그 대표적인 예 입니다.
이 방법은 md5sum
N + 1 번을 호출하는 다소 비효율적입니다. 여기서 N은 트리의 파일 수이지만 파일 및 디렉토리 메타 데이터 해시를 피하는 데 필요한 비용입니다.
옵션 2 : 데이터 와 메타 데이터 비교
파일 내용뿐만 아니라 트리의 모든 내용이 변경 되었음을 감지해야하는 경우 tar
디렉토리 내용을 압축하여 요청하십시오 md5sum
.
$ tar -cf - somedir | md5sum
tar
파일 권한, 소유권 등도 볼 수 있기 때문에 파일 내용의 변경뿐만 아니라 그에 대한 변경도 감지합니다.
이 방법은 트리를 한 번만 통과하고 해시 프로그램을 한 번만 실행하기 때문에 상당히 빠릅니다.
위의 find
기본 방법 과 마찬가지로 tar
기본 파일 시스템이 반환하는 순서대로 파일 이름을 처리합니다. 응용 프로그램에서 이러한 일이 발생하지 않도록 할 수도 있습니다. 그럴 가능성이있는 세 가지 다른 사용 패턴을 생각할 수 있습니다. (우리는 지정되지 않은 동작 영역에 들어가기 때문에 그것들을 나열하지 않을 것입니다. 각 파일 시스템은 OS의 버전마다 다를 수 있습니다.)
자신이 오 탐지를 얻는다면 Gilles ‘answer 의 find | cpio
옵션을 사용하는 것이 좋습니다 .
답변
체크섬은 파일을 문자열로 결정적이고 명확하게 표현해야합니다. 결정 론적이란 동일한 위치에 동일한 파일을 배치하면 동일한 결과를 얻을 수 있음을 의미합니다. 명백한 것은 두 개의 서로 다른 파일 세트가 서로 다른 표현을 가지고 있음을 의미합니다.
데이터 및 메타 데이터
파일을 포함하는 아카이브를 만드는 것이 좋습니다. 이것은 명백한 표현입니다 (아카이브를 추출하여 파일을 복구 할 수 있기 때문에). 날짜 및 소유권과 같은 파일 메타 데이터를 포함 할 수 있습니다. 그러나 이것은 아직 옳지 않습니다. 아카이브는 파일이 저장된 순서와 압축에 적용 가능한 경우에 따라 다르기 때문에 모호합니다.
해결책은 파일 이름을 아카이브하기 전에 정렬하는 것입니다. 파일 이름에 줄 바꿈이 포함되어 있지 않으면 파일 find | sort
을 나열하여 순서대로 아카이브에 추가 할 수 있습니다. 아카이버에게 디렉토리로 돌아 가지 않도록주의하십시오. POSIX pax
, GNU tar 및 cpio의 예는 다음과 같습니다 .
find | LC_ALL=C sort | pax -w -d | md5sum
find | LC_ALL=C sort | tar -cf - -T - --no-recursion | md5sum
find | LC_ALL=C sort | cpio -o | md5sum
이름과 내용 만, 최첨단 방식
메타 데이터가 아닌 파일 데이터 만 고려하려는 경우 파일 내용 만 포함하는 아카이브를 만들 수 있지만이를위한 표준 도구는 없습니다. 파일 내용을 포함하는 대신 파일의 해시를 포함시킬 수 있습니다. 파일 이름에 줄 바꿈이없고 일반 파일과 디렉토리 만있는 경우 (심볼릭 링크 나 특수 파일이없는 경우) 매우 쉽지만 몇 가지 사항을주의해야합니다.
{ export LC_ALL=C;
find -type f -exec wc -c {} \; | sort; echo;
find -type f -exec md5sum {} + | sort; echo;
find . -type d | sort; find . -type d | sort | md5sum;
} | md5sum
빈 디렉토리는 보이지 않으므로 체크섬 목록과 함께 디렉토리 목록을 포함합니다. 파일 목록이 정렬되어 있습니다 (Peter.O 덕분에 특정 재현 가능한 로케일로). echo
두 부분을 분리합니다 (이것없이 md5sum
일반 파일을 전달할 수있는 출력 처럼 보이는 빈 디렉토리를 만들 수 있습니다). 길이 확장 공격 을 피하기 위해 파일 크기 목록도 포함합니다 .
그건 그렇고, MD5는 더 이상 사용되지 않습니다. 사용 가능한 경우 SHA-2 또는 SHA-1 이상을 사용하십시오.
이름의 개행을 지원하는 이름과 데이터
다음은 GNU 도구를 사용하여 파일 이름을 null 바이트로 구분하는 위의 코드 변형입니다. 이렇게하면 파일 이름에 줄 바꾸기가 포함될 수 있습니다. GNU 다이제스트 유틸리티는 출력에서 특수 문자를 인용하므로 모호한 줄 바꿈이 없습니다.
{ export LC_ALL=C;
du -0ab | sort -z; # file lengths, including directories (with length 0)
echo | tr '\n' '\000'; # separator
find -type f -exec sha256sum {} + | sort -z; # file hashes
echo | tr '\n' '\000'; # separator
echo "End of hashed data."; # End of input marker
} | sha256sum
보다 강력한 접근법
다음은 파일 계층 구조를 설명하는 해시를 빌드하는 최소한의 테스트를 거친 Python 스크립트입니다. 디렉토리 및 파일 내용을 고려하고 기호 링크 및 기타 파일을 무시하고 파일을 읽을 수 없으면 치명적인 오류를 반환합니다.
#! /usr/bin/env python
import hashlib, hmac, os, stat, sys
## Return the hash of the contents of the specified file, as a hex string
def file_hash(name):
f = open(name)
h = hashlib.sha256()
while True:
buf = f.read(16384)
if len(buf) == 0: break
h.update(buf)
f.close()
return h.hexdigest()
## Traverse the specified path and update the hash with a description of its
## name and contents
def traverse(h, path):
rs = os.lstat(path)
quoted_name = repr(path)
if stat.S_ISDIR(rs.st_mode):
h.update('dir ' + quoted_name + '\n')
for entry in sorted(os.listdir(path)):
traverse(h, os.path.join(path, entry))
elif stat.S_ISREG(rs.st_mode):
h.update('reg ' + quoted_name + ' ')
h.update(str(rs.st_size) + ' ')
h.update(file_hash(path) + '\n')
else: pass # silently symlinks and other special files
h = hashlib.sha256()
for root in sys.argv[1:]: traverse(h, root)
h.update('end\n')
print h.hexdigest()
답변
md5deep 을 보십시오 . 관심을 가질만한 md5deep의 일부 기능 :
재귀 작업-md5deep은 전체 디렉토리 트리를 재귀 적으로 검사 할 수 있습니다. 즉, 디렉토리의 모든 파일 및 모든 서브 디렉토리의 모든 파일에 대해 MD5를 계산하십시오.
비교 모드-md5deep은 알려진 해시 목록을 받아 입력 파일 세트와 비교할 수 있습니다. 프로그램은 알려진 해시 목록과 일치하는 입력 파일 또는 일치하지 않는 입력 파일을 표시 할 수 있습니다.
…
답변
목표가 두 디렉토리 사이의 차이점을 찾는 것이라면 diff 사용을 고려하십시오.
이 시도:
diff -qr dir1 dir2
답변
모든 파일을 재귀 적으로 해시 한 다음 결과 텍스트를 해시 할 수 있습니다.
> md5deep -r -l . | sort | md5sum
d43417958e47758c6405b5098f151074 *-
md5deep 이 필요합니다.
답변
파일 이름을 제외한 파일 내용 만
내용이 다른 디렉토리에 있기 때문에 파일 이름 만 확인한 버전이 필요했습니다.
이 버전 (Warren Young ‘s answer) 은 많은 도움이되었지만 내 버전의 md5sum
파일 이름은 (명령을 실행 한 경로와 관련하여) 파일 이름 을 출력하고 폴더 이름은 다릅니다. 따라서 개별 파일 체크섬이 일치하더라도 최종 체크섬은 ‘티.
이를 해결하기 위해 필자의 경우 find
출력 의 각 줄에서 파일 이름을 제거해야했습니다 (을 사용하여 공백으로 구분 된 첫 번째 단어 만 선택하십시오 cut
).
find -s somedir -type f -exec md5sum {} \; | cut -d" " -f1 | md5sum
답변
해결책 :
$ pip install checksumdir
$ checksumdir -a md5 assets/js
981ac0bc890de594a9f2f40e00f13872
$ checksumdir -a sha1 assets/js
88cd20f115e31a1e1ae381f7291d0c8cd3b92fad
작동 신속 하고 쉽게 다음 솔루션 bash는 스크립트.