디렉토리에 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=always
diff
less -R
bash
대신 과 동일 zsh
하지만 버전 4.4 이상(용)과 및 유틸리티 readarray -d
(및 확장용)의 GNU 구현(또는 호환 가능)을 가정합니다.find
sort
-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와 다른지 확인할 수 있다는 것입니다.