OP의 @vume 아이디어의 쉘스크립트 구현

OP의 @vume 아이디어의 쉘스크립트 구현

fdupes와 같은 도구는 jpg 또는 h264 압축 파일 작업에 있어 터무니없는 과잉입니다. 파일 크기가 완전히 동일한 두 개의 파일은 두 파일이 동일하다는 좋은 표시입니다.

그 외에도 16바이트의 등간격 청크 16개를 추출하여 비교한 결과 역시 동일하다면 동일하다고 가정할 수 있는 증거는 충분합니다. 그런 게 있나요?

(그런데, 1MB 또는 CD/DVD 1개와 같은 특정 대상 크기로 압축하는 옵션이 있기 때문에 파일 크기 자체는 다소 신뢰할 수 없는 측정 기준일 수 있다는 것을 알고 있습니다. 많은 파일에서 동일한 대상 크기를 사용하는 경우 이는 다음과 같습니다. 일부 다른 파일의 크기가 정확히 동일한 것은 상당히 합리적입니다.

답변1

치카오카중복 파일(이미지, 비디오 또는 음악 포함)을 찾아 속도에 중점을 두고 명령줄이나 그래픽 인터페이스를 통해 표시하도록 설계된 오픈 소스 도구입니다. 이것부분적으로 문서에서당신은 관심이 있을 수 있습니다:

대량의 복제본을 더 빠르게 스캔

기본적으로 부분 해시는 동일한 크기(파일당 해시 2KB만)로 그룹화된 모든 파일에 대해 계산됩니다. 이 해시 값의 계산은 일반적으로 특히 SSD 및 빠른 멀티 코어 프로세서에서 매우 빠릅니다. 그러나 HDD나 느린 프로세서를 사용하여 수십만 또는 수백만 개의 파일을 검색하는 경우 이 단계는 종종 오랜 시간이 걸릴 수 있습니다.

GUI 버전에서는 해시가 캐시에 저장되므로 향후 중복 항목 검색이 더 빨라집니다.


예:

몇 가지 테스트 파일을 만듭니다.

무작위 이미지를 생성한 다음 복사하여 a.jpg복사본 b.jpg을 얻습니다.

$ convert -size 1000x1000 plasma:fractal a.jpg
$ cp -v a.jpg b.jpg
'a.jpg' -> 'b.jpg'
$ convert -size 1000x1000 plasma:fractal c.jpg
$ convert -size 1000x1000 plasma:fractal d.jpg
$ ls --size
total 1456
364 a.jpg  364 b.jpg  364 c.jpg  364 d.jpg

사이즈만 확인하세요:

$ linux_czkawka_cli dup --directories /run/shm/test/ --search-method size
Found 2 files in 1 groups with same size(may have different content) which took 361.76 KiB:
Size - 361.76 KiB (370442) - 2 files 
/run/shm/test/b.jpg
/run/shm/test/a.jpg

해시 값으로 파일을 확인하십시오.

$ linux_czkawka_cli dup --directories /run/shm/test/ --search-method hash
Found 2 duplicated files in 1 groups with same content which took 361.76 KiB:
Size - 361.76 KiB (370442) - 2 files 
/run/shm/test/b.jpg
/run/shm/test/a.jpg

파일을 이미지로 분석하여 검사합니다.

$ linux_czkawka_cli image --directories /run/shm/test/
Found 1 images which have similar friends
/run/shm/test/a.jpg - 1000x1000 - 361.76 KiB - Very High
/run/shm/test/b.jpg - 1000x1000 - 361.76 KiB - Very High

답변2

편집할 수 있는 메타데이터를 보관할 수 있는 첫 번째와 마지막 1MiB 정도의 전체 비교(또는 해시)를 수행하고 싶을 수도 있습니다.아니요압축된 데이터에 오프셋을 도입합니다. 또한 저장소에서 읽는 단위는 일반적으로 16바이트가 아닌 512바이트이므로 더 많은 데이터를 비교하기 위한 약간의 추가 CPU 시간은 무시할 수 있습니다. (512바이트 경계로 정렬)

(쓰기 섹터 크기는 일반적으로 최소 4096B이지만 논리적 섹터 크기가 512이면 커널 자체가 요청을 전체 페이지로 확대하지 않는 경우 SATA 디스크가 요청된 512B만 유선을 통해 보낼 수 있습니다. 그럴 수도 있습니다. 페이지 캐시는 페이지에서 완전히 관리됩니다.


기억해주세요비트 로트 가능, 특히 파일이 DVD-R 또는 기타 광학 미디어에 저장된 경우. 비트별 동등성을 확인하지 않고 "중복"을 제거하지 않습니다.(또는 적어도 동일한 해시). 파일의 이전 부분에서 해시 서명을 기반으로 중복 항목을 신속하게 제외하는 것이 유용하지만 대부분의 경우 두 파일을 중복 항목으로 선언하기 전에 철저한 확인을 수행해야 합니다.


두 파일이 거의 동일하지만 약간의 차이가 있는 경우 ffmpeg -i foo.mp4 -f null -FindFault를 사용하고 디코딩하지만 출력에는 아무 작업도 수행하지 않습니다.

비트별 차이를 찾았지만 두 파일 모두 디코더가 알아차린 오류가 없는 경우 다음을 사용하세요.

ffmpeg -i foo.mp4 -f framecrc  foo.fcrc

또는 -f framemd5어떤 프레임이 다르지만 잘못된 h.264 스트림이 아닌지 확인하세요. 그런 다음 그곳을 살펴보고 어느 것이 손상되었는지 육안으로 확인하십시오.

귀하의 접근 방식이 적합할 수 있습니다.발각서로의 복사본이 손상된(또는 메타데이터로 편집된) 파일,이는 일반 중복 파인더가 쉽게 할 수 없는 작업입니다. 이 질문 상태에 대한 댓글jdupes파일의 첫 번째 NMB의 해시 값을 사용할 수 있습니다.크기를 비교한 후에는 올바른 방향으로 나아가는 단계입니다.


다른 사용 사례의 경우 덜 엄격한 검사를 허용할 수 있지만 동일한 크기의 파일이 있는 경우에만 비교하거나 해시하는 중복 파일 찾기가 있는 경우 해당 중 하나를 실행하도록 할 수 있습니다(밤새 또는 외출 시). 그런 다음 전체 확인 목록을 가지고 돌아옵니다.

일부 도구에는 fslint중복 파일을 함께 하드 링크(또는 심볼릭 링크)하여 다음에 중복 파일을 찾을 때 이미 동일한 파일이 되도록 하는 옵션이 있습니다. 따라서 내 경험에 따르면 중복 파일을 찾는 것이 더 빠르지만 위험한 접근 방식을 보장한다고 생각하지 않습니다.

( fslint분명히 Python3은 업데이트되지 않았습니다.czkawkaRust를 기반으로 한 최신 복제품입니다.아쿠 벤투 답변.)

답변3

GNU가 cmp당신을 도와줄 수 있나요?

  • -s이 옵션을 사용하면 출력을 억제하고 반환 값만 사용할 수 있습니다 .
  • 다양한 파일 크기 비교를 건너뛰기 위해 먼저 파일 크기를 확인합니다.
  • -i(초기 건너뛰기) 및 -n(비교할 바이트 수) 옵션을 사용하여 비교할 바이트 범위를 추가로 정의할 수 있습니다.

cmp각 파일 쌍에 대한 파일 수가 너무 많으면 먼저 sort모든 파일을 파일 크기별로 비교한 다음 크기가 같은 그룹만 비교할 uniq -D수 있습니다 -w(

답변4

OP의 @vume 아이디어의 쉘스크립트 구현

배경 및 예시rsync

구경하다 rsync. 파일이 동일한지 확인하는 여러 수준이 있습니다. 설명서는 man rsync매우 상세하므로 내가 설명하는 내용을 식별할 수 있을 것이며 다른 흥미로운 대안이 있을 수도 있습니다.

  • 가장 엄격한 검사는 바이트 단위로 비교하는 것이지만, 쓸 때 전체 백업 등 데이터가 많으면 시간이 많이 걸린다.

    -c, --checksum              skip based on checksum, not mod-time & size
    -a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)
    
  • 표준 검사는 크기 및 기타 파일 속성(예: 타임스탬프)입니다. 일반적으로 충분히 좋은 것으로 간주됩니다.

  • 귀하의 아이디어 @vume은 이 두 가지 검사 수준 사이에 있는 것을 의미합니다. 아직 그런 도구를 본 적은 없지만 매우 관심을 갖고 싶습니다.

편집 1: 쉘 스크립트vumer

다음 쉘스크립트 는 당신이 원하는 @vume을 수행하는 vumer데 사용됩니다 .dd

#!/bin/bash

chunks=16
chnksiz=16

function usage {
 echo "Usage: ${0##*/} <file>"
}

if ! test -f "$1"
then
 usage
 exit
fi

size=$(stat --format='%s' "$1")
step=$(( size/(chunks-1) ))
#echo "step=$step"
tmpfil=$(mktemp)

if [ $size -lt 512 ]
then
 chksum=$(md5sum "$1" | sed 's/ .*//')
else
 for (( i=0;i<chunks;i++ ))
 do
  if [ $i -eq $((chunks-1)) ]
  then
   pos=$((size-chnksiz))
  else
   pos=$((i*step))
  fi
#  echo "$i: $pos"
  dd if="$1" bs=1 skip=$pos count=16 >> "$tmpfil" 2> /dev/null
 done
 chksum=$(md5sum "$tmpfil" | sed 's/ .*//')
fi

modif=$(stat --format='%y' "$1")
modif=${modif//\ /_}
echo "size=$size modif=$modif checksum=$chksum file=\"$1\""
#less "$tmpfil"
rm "$tmpfil"

내 Lenovo C30 워크스테이션(오래되었지만 강력함)에서 vumerUbuntu Desktop 22.04 LTS iso 파일로 테스트하고 소요된 시간을 비교했습니다 md5sum.

$ time vumer ubuntu-22.04-desktop-amd64.iso
size=3654957056 modif=2022-04-19_10:25:02.000000000_+0200 checksum=ec3483153bfb965745753c4b1b92bf2e file="ubuntu-22.04-desktop-amd64.iso"

real    0m0,024s
user    0m0,018s
sys 0m0,008s

$ time md5sum ubuntu-22.04-desktop-amd64.iso
7621da10af45a031ea9a0d1d7fea9643  ubuntu-22.04-desktop-amd64.iso

real    0m19,919s
user    0m5,331s
sys 0m0,988s

md5sum따라서 대용량 파일의 경우 요즘에는 [너무] 간단한 체크섬 도구로 간주되는 것 보다 훨씬 빠릅니다 . sha256sum심지어 더 느립니다.

quiet splashpersistence또한 여러 부팅 옵션을 원본 파일로 대체하기 위해 변환된 데비안 iso 파일을 확인 하고 비교했습니다. vumer불행하게도 수정을 위해 몇 군데 위치를 확인하지 않았습니다. 따라서 여기서는 차별화를 위해 클래식 타임스탬프를 사용해야 합니다. 물론 md5sum알 수 있습니다.

$ vumer debian-live-10.0.0-amd64-standard.iso
size=865075200 modif=2019-09-05_10:14:31.000000000_+0200 checksum=b8af03a946fb400ca66f2bdb2a6bb628 file="debian-live-10.0.0-amd64-standard.iso"

$ vumer persistent-debian-live-10.0.0-amd64-standard.iso
size=865075200 modif=2019-09-12_18:01:55.000000000_+0200 checksum=b8af03a946fb400ca66f2bdb2a6bb628 file="persistent-debian-live-10.0.0-amd64-standard.iso"

$ md5sum  *debian-live-10.0.0-amd64-standard.iso
a64ae643520ca0edcbcc769bae9498f3  debian-live-10.0.0-amd64-standard.iso
574ac1f29a6c86d16353a54f6aa8ea1c  persistent-debian-live-10.0.0-amd64-standard.iso

따라서 보유하고 있는 파일 유형, 수정 방법, vumer이와 같은 도구가 유용한지 여부에 따라 달라집니다.

편집 2: "oneliner"에 대한 디렉토리 트리 스캔

이것은 디렉토리 트리를 스캔하는 "oneliner"입니다.

md5sum $(for i in $(find -type f -ls|sed 's/^ *//'|tr -s ' ' '\t     '| \
cut -f 7,11|sort -n|sed 's/\t/\t     /'|uniq -Dw10|sed 's/\t */\t/'| \
cut -f 2 );do vumer "$i";done|sed -e 's/.*checksum=//'|sort|rev| \
uniq -f 1 -D|rev|tee /dev/stderr|sed -e 's/.*file=//' -e 's/"//g')|uniq -Dw32
  • 디렉토리 트리에는 418개의 파일이 있습니다(iso 파일 및 기타 파일 포함).
  • 식별된 크기 72개 파일 확인(아마도 36쌍)
  • vumer동일한 vumer 체크섬으로 식별된 파일 30개(15쌍)
  • md5sum동일한 md5sum 체크섬으로 식별된 18개 파일(9쌍)

즉 , 418개 파일 중 30개만 확인하면 되므로 vumer시간이 크게 절약 됩니다.md5sum

편집 3: 쉘 스크립트scan4dblt

scan4dblt"oneliner"를 여러 디렉토리 트리에서 테스트하고 "doer" 스크립트를 일부 편집한 스크립트로 대체 했습니다 vumer.

#!/bin/bash

function mkfil {

tmpf0=$(mktemp)
tmpf1=$(mktemp)
tmpf2=$(mktemp)
tmpf3=$(mktemp)
tmpf4=$(mktemp)
tmpf5=$(mktemp)
}

function rmfil {

rm "$tmpf0" "$tmpf1" "$tmpf2" "$tmpf3" "$tmpf4" "$tmpf5"
}

# main

echo -n "${0##*/}: "
mkfil

# same size

find -type f -printf "%s %p\n" \
|sed 's/ /        /'|sort -n|uniq -Dw11|tee "$tmpf0" |tr -s ' ' ' ' \
|cut -d ' ' -f 2- |sed -e 's/&/\&/g' -e 's/(/\(/g' -e 's/)/\)/g' > "$tmpf1"

res=$(wc -l "$tmpf0"|sed 's/ .*//')
if [ $res -gt 1 ]
then
 echo "same size ($res):"
 cat "$tmpf0"
else
 echo "no files with the same size"
 rmfil
 exit 1
fi

# vumer

while read fnam
do
 echo -n '.'
 vumer "$fnam" >> "$tmpf2"
# echo -e "$fnam: $(vumer "$fnam")" >> "$tmpf2"
done < "$tmpf1"
echo ''
sed "$tmpf2" -e 's/.*checksum=//'|sort|uniq -Dw33|tee "$tmpf1" |sed -e 's/.*file=//' -e 's/"//g' > "$tmpf3"

res=$(wc -l "$tmpf1"|sed 's/ .*//')
if [ $res -gt 1 ]
then
 echo "vumer: ($res)"
 cat "$tmpf1"
else
 echo "vumer: no files with the same checksum"
 rmfil
 exit 1
fi

# inode

while read fnam
do
 echo -n '.'
 size=$(stat --format='%s' "$fnam")
 inod=$(stat --format='%i' "$fnam")
 printf "%12d %10d %s\n" $size $inod "$fnam" >> "$tmpf4"
done < "$tmpf3"
echo ''
#cat "$tmpf4"
#cat "$tmpf4" |sort -k3|uniq -f2 -Dw32 |sort -n > "$tmpf5"
cat "$tmpf4" |sort -k2|uniq -f1 -Dw11 |sort -n > "$tmpf5"

> "$tmpf2"
while read fnam
do
 if ! grep "$fnam" "$tmpf5" 2>&1 > /dev/null
 then
  echo "$fnam" >> "$tmpf2"
 fi
done < "$tmpf3"

res=$(wc -l "$tmpf5"|sed 's/ .*//')
if [ $res -gt 1 ]
then
 echo "inode: ($res)"
 echo "        size     inode              md5sum                 file-name"
 cat "$tmpf5"
else
 echo "inode: no files with the same inode"
fi

# md5sum

> "$tmpf4"
while read fnam
do
 echo -n '.'
 size=$(stat --format='%s' "$fnam")
 inod=$(stat --format='%i' "$fnam")
 printf "%12d %10d " $size $inod >> "$tmpf4"
 md5sum "$fnam" >> "$tmpf4"
done < "$tmpf2"
echo ''
#echo "4: ";cat "$tmpf4"
cat "$tmpf4" |sort -k3|uniq -f2 -Dw33 |sort -n > "$tmpf5"

res=$(wc -l "$tmpf5"|sed 's/ .*//')
if [ $res -gt 1 ]
then
 echo "md5sum: ($res)"
 echo "        size     inode              md5sum                 file-name"
 cat "$tmpf5"
else
 echo "md5sum: no files with the same checksum"
 rmfil
 exit 1
fi

rmfil

편집 4: 향상된 쉘스크립트 scan4dblt와 예제(출력 파일)

쉘스크립트는 scan4dblt대용량 iso 파일, 이미지, 비디오 클립 및 문서를 포함한 여러 디렉토리 트리를 사용하여 추가로 개발 및 테스트되었습니다. 몇 가지 버그가 수정되었습니다(여기서는 현재 버전이 원본 버전을 대체합니다).

예:

다음 예에서는 생성된 출력 파일을 보여줍니다.

scan4dblt | tee /tmp/scan4dblt.out

파일의 작은 부분이 완전히 검사되지만 md5sum전체 검사는 대부분의 실행 시간을 차지합니다. 시간 척도는 md5sum파일 크기에 따라 다릅니다.

특히 상대적으로 작은 파일이 많은 경우 쉘스크립트를 통한 구현 효율성은 매우 낮고 컴파일된 프로그램은 훨씬 좋아질 것입니다. 그러나 iso 파일이나 비디오 클립과 같은 대용량 파일의 경우 쉘스크립트가 아마도 잘 작동할 것입니다.

편집 5: 쉘스크립트에 대한 추가 설명

이 연습을 다시 하게 된다면 먼저 하드 링크로 인해 이중선을 별도로 저장하고 나머지 [하드 링크] 파일을 목록에 유지하여 나중에 비교할 때 다른 파일과 일치하는지 확인하겠습니다.

vumer[여기서 호출된 도구에 대해] 좋은 작업을 수행하기 위해 테스트에서 얼마나 큰 데이터 덩어리를 확인해야 하는지 보는 것도 흥미로울 것입니다. 중복을 확인하려는 파일 형식에 맞게 조정해야 할 수도 있습니다.

또한 중간 검사에 어떤 파일 크기가 유용한지 테스트하겠습니다 vumer.

마지막(?)댓글

이 질문이 답변과 댓글 모두에서 많은 관심을 받고 있다는 사실을 알게 되어 기쁩니다. Peter Cordes가 자신의 답변(및 주석)에 쓴 것처럼 빠른 테스트 도구(내 경우에는 vumer)는 테스트 중인 파일 유형에 따라 여러 가지 방법으로 개선될 수 있습니다.

내 대답에서는 @vume의 원래 아이디어만 구현했으며 많은 경우 다른 빠른 정렬 방법과 결합하면 전체 체크섬 테스트의 필요성을 최소화하기에 충분하다는 것을 보여줄 수 있습니다.

관련 정보