디렉터리의 파일 비교

디렉터리의 파일 비교

디렉토리에 x개의 파일이 있고(x = 100보다 큼) 이 파일의 차이점을 비교하고 싶다고 가정합니다. 이 작업을 어떻게 수행할 수 있나요? 저는 Ubuntu 18.04 머신을 실행하고 있습니다. 논의를 위해 디렉토리가 /home/user1/music_list/이고 해당 디렉토리에 있는 파일 중 하나가 /home/user1/music_list/jazz1.txt라고 가정합니다.

답변1

이는 실제로 파일이 본질적으로 동일한지 여부에 따라 달라집니다. 수천 개의 비교를 제시하는 것도 "참조 버전"이나 일련의 점진적 수정을 식별할 수 없으면 완전히 혼란스럽습니다.

한번은 신뢰성 문제가 있는 배출 메커니즘 문제를 해결해 달라는 요청을 받은 적이 있습니다. 전력망 사이트의 각 계층에는 16,000개의 이미지 파일, 즉 250만 개의 파일이 있는 160개의 서버가 있습니다.

기본적으로 가장 인기 있는 버전에 투표해 달라고 요청했습니다. 각 서버에는 자체 파일 체크섬이 있고 체크섬, 날짜, 크기, 이름 목록을 나에게 보냅니다. 체크섬으로 그룹화하고 계산합니다. 전체 컬렉션에서 100% 일관성이 있는 모든 파일이 가능합니다. 사례의 80% 이상과 일치하는 항목에는 업데이트가 누락된 서버가 표시됩니다. 20% 미만이면 삭제에 실패했거나 악성 테스트 파일입니다. 20~80% 범위에 드는 사람은 거의 없습니다.

내 사용 사례에서는 잘못된 이름이나 경로로 다른 서버에 업로드된 이미지 파일을 감지하는 것도 쉬웠습니다.

이 접근 방식은 문제를 해결하지 못할 수도 있지만 필요한 세부 비교 횟수를 크게 줄여줍니다.

답변2

이 스크립트를 사용해 볼 수 있습니다.

diff선호하는 출력에 따라 또는 명령을 추가했습니다 .comm

for i in /home/user1/music_list/*.txt; do
        index_file="$i"
        echo "$(tput setaf 1)Comparing "$i" $(tput sgr 0)"
        for n in /home/user1/music_list/*.txt; do
                next_file="$n"
                echo "$(tput setaf 5)With "$n" $(tput sgr 0)"
                #comm -3 <(sort "$index_file") <(sort "$next_file")
                diff -s <(sort "$index_file") <(sort "$next_file")
                shift
        done
done

으로 출력comm

Comparing z.txt
With z1.txt
With z2.txt
1
        2
With z3.txt
1
        22
With z4.txt
1
        222

comm이름이 동일한 경우 이름은 인쇄되지만 출력되지는 않습니다.z1.txt

으로 출력diff

Comparing z.txt
With z1.txt
Files /dev/fd/63 and /dev/fd/62 are identical
With z2.txt
1c1
< 1
---
> 2
With z3.txt
1c1
< 1
---
> 22
With z4.txt
1c1
< 1
---
> 222

답변3

/some/dir모든 일반 파일을 일대일로 (재귀적으로) 비교하려면 다음을 수행할 수 있습니다 zsh.

function {
  local fileA fileB
  for fileA do
    shift
    for fileB do
      diff -su $fileA $fileB
    done
  done
} /some/dir/**/*(ND.)

이는 동일한 형식과 컨텍스트의 차이점 -u과 파일이 동일할 때 -s(비표준) 보고서를 보여줍니다.

그러나 파일이 100개가 넘으면 수천 번의 일대일 비교가 필요합니다.

GNU를 사용하면 옵션을 diff추가 하고 익명 함수의 출력을 전달하여 해당 출력을 더 수용 가능하게 만들 수 있습니다.--color=alwaysdiffless -R

bash대신 과 동일 zsh하지만 버전 4.4 이상(용)과 및 유틸리티 readarray -d(및 확장용)의 GNU 구현(또는 호환 가능)을 가정합니다.findsort-print0-z

(
  readarray -td '' files < <(
    find /some/dir/ -type f -print0 | sort -z)
  set -- "${files[@]}"
  for fileA do
    shift
    for fileB do
      diff -su "$fileA" "$fileB"
    done
  done
)

중복 항목이 많은 경우 먼저 어떤 파일이 동일한지 확인한 다음 동일한 파일의 각 그룹에서 하나의 파일만 선택하여 다른 그룹의 한 파일과 비교함으로써 비교 횟수를 줄일 수 있습니다.

그리고 zsh:

typeset -A set
files=(/some/dir/**/*(ND.))
for file in $files; do
  sum=$(sha1sum < $file) || continue
  # store the list of files having a given checksum NUL delimited
  # in an associative array
  set[$sum]+=$file$'\0'
done
sums=(${(k)set})
for sum1 in $sums; do
  shift 1 sums
  files1=(${(0)set[$sum1]}) # split on NUL
  (( $#files < 2 )) || print -r All of ${(j[, ])files1} are identical
  for sum2 in $sums; do
    files2=(${(0)set[$sum2]})
    diff -u $files1[1] $files2[1]
  done
done

(검증되지 않은).

답변4

/home/user1/music_list/ 디렉토리에 있는 단 하나의 파일만이 고유하다는 것을 나에게 알려줌으로써 위의 문제가 개선되었다고 가정해 보십시오. 유일한 파일이 무엇인지 찾으려면 다음 답변을 고려하고 어떻게 생각하는지 알려주십시오.

$diff -r --from-file=/home/user1/music_list/jazz1.txt /home/user1/music_list/

아이디어는 ./jazz.txt 디렉토리의 파일을 동일한 디렉토리의 다른 모든 파일과 비교하여 어떤 파일이 jazz.txt와 다른지 확인할 수 있다는 것입니다.

관련 정보