두 개의 zip으로 압축 된 파일이 같은지 어떻게 확인할 수 있습니까?


11

단순히 텍스트 파일로 데이터를 덤프하여 "멍청한"백업을 수행하는 동안 공간을 절약하려고합니다. 내 백업 스크립트는 매일 실행되며 다음과 같습니다.

  1. 백업 날짜를 따서 명명 된 디렉토리를 만듭니다.
  2. 일부 데이터를 텍스트 파일로 덤프하십시오 "$name".
  3. 파일이 유효하면 gzip으로 압축하십시오 gzip "$name". 그렇지 않으면 rm "$name".

이제 전날에도 동일한 데이터를 사용할 수있는 경우 파일을 제거하는 추가 단계를 추가하고 싶습니다 (그리고 심볼릭 링크 또는 하드 링크를 만듭니다).

처음에는을 사용하려고 생각 md5sum "$name"했지만 파일 이름과 생성 날짜도 저장하기 때문에 작동하지 않습니다.

않습니다 gzip이 개 gzip으로 압축 된 파일을 비교하고 같은지 여부 말해 할 수있는 옵션이? 경우 gzip이러한 옵션이 없습니다, 내 목표를 달성하기위한 또 다른 방법은 무엇입니까?


1
이것을보십시오 : linux.die.net/man/1/zdiff
mreithub

2
나는 제안하려고 diff <(zcat file1) <(zcat file2)했지만 mrethub의 제안 zdiff은 훨씬 좋아 보인다.
케빈

backuppc은 수동으로 달성하기 위해 무엇을하려고하는 당신을 위해 수행
drone.ah

그것은 하루에 하나 개의 파일 인 경우 @ drohne.ah의 backuppc (나는 그것이 GZIP에 의미를 많이 만드는 SQL 덤프처럼의 STH를 추측) ... 종류 잔인한의 수도
mreithub

1
@mdpc MD5의 알고리즘 문제는 관련이 없을 것입니다. 충돌을 구성 할 수는 있지만 공격자가 아니라 우연히 발생하는 문제 일 수 있습니다. ~ 2 ^ 64 개의 파일이있을 때까지는 여전히 발생하지 않을 것입니다. 사전 이미지 공격조차 중요하지 않습니다.
derobert

답변:


7

그의 의견 (또는 Kevin의 명령, 비슷한)에서 mreithub이 제안한대로 zcmp또는 zdiff을 사용할 수 있습니다 . 이들은 실제로 두 파일의 압축을 풀고 cmp또는 로 전달하기 때문에 상대적으로 비효율적 diff입니다. "동일하다"라고 대답하고 싶다면 cmp훨씬 더 빠를 것입니다.

의 접근 방식 md5sum은 완벽하지만 실행 하기 전에 MD5를 가져와야 합니다 gzip. 그런 다음 결과 .gz파일 과 함께 파일에 저장 하십시오. 그런 다음 압축하기 전에 파일을 쉽게 비교할 수 있습니다. 이름이 같으면 md5sum -c이 작업을 수행합니다.

$ mkdir "backup1"
$ cd backup1
$ echo "test" > backup-file
$ md5sum backup-file > backup-file.md5
$ gzip -9 backup-file

그리고 다음 백업 :

$ mkdir "backup2"
$ cd backup2
$ echo "test" > backup-file
$ md5sum -c ../backup1/backup-file.md5 
backup-file: OK

따라서 변경되지 않았습니다. OTOH, 바뀌었다 :

$ echo "different" > backup-file
$ md5sum -c ../backup1/backup-file.md5 
backup-file: FAILED
md5sum: WARNING: 1 computed checksum did NOT match

전달 --quiet하면 종료 코드 만 제공됩니다. 일치하는 경우 0, 차이가없는 경우 0

MD5는 상당히 빠르지 만 굉장히 빠르지는 않습니다. MD4 ( openssl md4명령 줄에서 얻는 것이 가장 좋습니다)는 약 두 배 빠릅니다 (MD5도 안전하지는 않지만 아무도 파괴하려고 시도하지 않을 때 충돌에 약합니다). SHA-1 ( sha1sum)이 더 안전하지만 느립니다. SHA-256 ( sha256sum)은 안전하지만 여전히 느립니다. CRC32는 몇 배 빨라야하지만 더 짧아서 더 많은 랜덤 충돌이 발생합니다. 또한 완전히 안전하지 않습니다.


zdiff난 그냥 알고 싶어 같은 폐기물을 보인다 여부를 파일이 아니라 변경된 . zcmp흥미로워 보입니다.
Lekensteyn

7

@derobert 의 답변은 훌륭하지만 내가 찾은 다른 정보를 공유하고 싶습니다.

gzip -l -v

gzip 압축 파일에는 이미 해시가 포함되어 있습니다 (안전하지는 않지만 이 SO post 참조 ).

$ echo something > foo
$ gzip foo
$ gzip -v -l foo.gz 
method  crc     date  time           compressed        uncompressed  ratio uncompressed_name
defla 18b1f736 Feb  8 22:34                  34                  10 -20.0% foo

CRC와 압축되지 않은 크기를 결합하여 빠른 지문을 얻을 수 있습니다.

gzip -v -l foo.gz | awk '{print $2, $7}'

cmp

두 바이트가 같은지 여부를 확인하려면을 사용하십시오 cmp file1 file2. 이제 gzip으로 압축 된 파일에는 데이터 및 바닥 글 (CRC + 원본 크기)이 추가 된 헤더가 있습니다. GZIP 파일 포맷의 설명 헤더 파일을 압축하고, 파일명은 10 바이트의 헤더 뒤에 첨부되는 문자열 NUL 종료되는 시간을 포함 보여준다.

따라서 파일 이름이 일정하고 동일한 명령 ( gzip "$name")이 사용되면 cmp시간을 포함하여 첫 번째 바이트를 사용 하고 건너 뛰어 두 파일이 다른지 여부를 확인할 수 있습니다 .

cmp -i 8 file1 file2

참고 : 동일한 압축 옵션이 중요하다는 가정하에 그렇지 않으면 명령은 항상 파일을 다른 것으로보고합니다. 이는 압축 옵션이 헤더에 저장되어 압축 된 데이터에 영향을 줄 수 있기 때문에 발생합니다. cmp원시 바이트 만보고 gzip으로 해석하지 않습니다.

길이가 같은 파일 이름이 있으면 파일 이름을 읽은 후 건너 뛸 바이트를 계산할 수 있습니다. 파일 이름의 크기가 다른 cmp경우와 같이 바이트를 건너 뛴 후 실행할 수 있습니다 cmp <(cut -b9- file1) <(cut -b10- file2).

zcmp

이것은 가장 좋은 방법입니다. 먼저 데이터를 압축하고 바이트를 비교하기 시작합니다 cmp(실제로 zcmp( zdiff) 셸 스크립트 에서 수행되는 작업입니다 ).

한 가지 참고 사항은 매뉴얼 페이지의 다음 참고 사항을 두려워하지 마십시오.

비교하기 전에 두 파일을 모두 압축 해제해야하는 경우 두 번째 파일은 / tmp로 압축 해제됩니다. 다른 모든 경우 zdiff 및 zcmp는 파이프 만 사용합니다.

충분히 새로운 Bash가 있으면 압축은 임시 파일을 사용하지 않고 파이프 만 사용합니다. 또는 zdiff출처에서 알 수 있듯이

# Reject Solaris 8's buggy /bin/bash 2.03.

바이트 4 (FLG)가 0이면 파일 이름이 헤더에 없으므로 길이에 대해 걱정할 필요가 없습니다. 또한 gzip -v -l헤더의 4 개의 MTIME 바이트가 0 인 경우 MTIME 대신 파일 시간을보고합니다. 또한 MTIME이있는 경우 압축이 시작된 시간이기 때문에 일반적으로 파일 시간보다 약간 앞서 있습니다.
kitchin

0

두 개의 gzip 파일을 비교하려면 내용, 하나의 명령, no diff만 비교하십시오.md5sum

$ diff -q <(zcat one.gz|md5sum|cut -f1 -d' ') \
          <(zcat two.gz|md5sum|cut -f1 -d' ') \
    && echo same || echo not_same

관련 차이점을 '필터링'할 수도 있습니다.

$ diff -q <(zcat one.gz|grep -v '^-- Dump completed'|md5sum|cut -f1 -d' ') \
          <(zcat two.gz|grep -v '^-- Dump completed'|md5sum|cut -f1 -d' ') \
   && echo same || echo not_same

스크립팅의 경우 필터 기능 (테스트되지 않은 예제)을 권장합니다.

do_filter_sum() {
  zcat $1 | grep -v '^-- Dump completed' | md5sum | cut -f1 -d' '
}

diff -q <(do_filter_sum one.gz) \
        <(do_filter_sum two.gz) \
        && echo same || echo not_same

md5sum은 낭비이므로 사용할 수 있습니다 cmp. zcatgrep병합 될 수 있습니다 zgrep.
Lekensteyn

사실, md5sum은 비교할 필요가 없습니다 (아직 생성하지 않은 경우). derobert가 사용한 이후로 방금 사용했습니다. zgrep은 기본적으로 gunzip 및 grep (또는 경우에 따라 sed)을 수행하는 스크립트이므로 차이가 거의 없습니다. 게시 된 스크립트는 의도적으로 플러그 가능한 부품이있는 파이프 체인으로 표시됩니다. 모든 것을 하나의 명령으로 병합하는 재미는 무엇입니까?
michael

1
그리고 zcat그냥 gunzip -c입니다. 올바른 작업에 적합한 도구를 사용하십시오. KISS는 부풀림보다 낫습니다. 이 경우 필요에 따라 하드 링크를 생성하는 무언가를 작성하는 데 시간을 할애합니다. 더 재미 있습니다.
Lekensteyn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.