답변:
diff toool을 사용할 수 있습니다 . -q 및 -r 옵션을 참조하십시오.
-q --brief
Output only whether files differ.
-r --recursive
Recursively compare any subdirectories found.
예:
diff -qr dir1 dir2
Only in
디렉토리가 이상적인 사본 인 경우에도 나타나는 말도 안되는 정보로 어수선 합니다. 변경 사항을 이전 개정과 비교하고 전체 개정을 별도의 디렉토리에 다운로드하고 표준 SVN 도구를 사용하여 비교해야했습니다. 가는 유일한 방법 인 것 같습니다…
diffutils
패키지는 포함 lsdiff
도구를. diff -u
lsdiff에 출력을 전달하십시오 .
diff -u --other-diff-options path1 path2 | lsdiff
patchutils
나를 위해 패키지에 있었습니다 (CentOS 5.x).
변경된 파일 이름 만 사용하려면 다음 명령을 사용하십시오.
diff -r dirt1 dir2 --brief | sed 's/^Only in \([^:]*\): /\1\//' | sed 's/^Files \(.*\) and .* differ/\1/'
일부 파일을 오브젝트 파일 또는 라이브러리 파일로 제외해야하는 경우 다음을 사용할 수 있습니다.
diff -r dirt1 dir2 --brief --exclude "*.o" --exclude "*.a" | sed 's/^Only in \([^:]*\): /\1\//' | sed 's/^Files \(.*\) and .* differ/\1/'
프로그래밍 방식으로 새 파일 또는 수정 된 파일 목록을 만들려면 rsync , sort 및 uniq을 사용하는 것이 가장 좋습니다 .
(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq
이 예제를 통해 설명하겠습니다. 두 개의 dokuwiki 릴리스를 비교하여 어떤 파일이 변경되었고 어떤 파일이 새로 생성되었는지 확인하려고합니다.
우리은 wget과 타르를 가져오고 디렉토리에 압축을 풉니 old/
과 new/
:
wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29d.tgz
wget http://download.dokuwiki.org/src/dokuwiki/dokuwiki-2014-09-29.tgz
mkdir old && tar xzf dokuwiki-2014-09-29.tgz -C old --strip-components=1
mkdir new && tar xzf dokuwiki-2014-09-29d.tgz -C new --strip-components=1
rsync를 한 가지 방법으로 실행하면 rsync와 diff의 비교가 다음과 같이 새로 작성된 파일을 놓칠 수 있습니다.
rsync -rcn --out-format="%n" old/ new/
다음과 같은 출력을 생성합니다.
VERSION
doku.php
conf/mime.conf
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php
한 방향으로 만 rsync를 실행하면 새로 작성된 파일이 누락되고 다른 방법으로 삭제 된 파일이 누락되면 diff의 출력을 비교하십시오.
diff -qr old/ new/
다음과 같은 출력을 생성합니다.
Files old/VERSION and new/VERSION differ
Files old/conf/mime.conf and new/conf/mime.conf differ
Only in new/data/pages: playground
Files old/doku.php and new/doku.php differ
Files old/inc/auth.php and new/inc/auth.php differ
Files old/inc/lang/no/lang.php and new/inc/lang/no/lang.php differ
Files old/lib/plugins/acl/remote.php and new/lib/plugins/acl/remote.php differ
Files old/lib/plugins/authplain/auth.php and new/lib/plugins/authplain/auth.php differ
Files old/lib/plugins/usermanager/admin.php and new/lib/plugins/usermanager/admin.php differ
rsync를 양방향으로 실행하고 중복을 제거하기 위해 출력을 정렬하면 디렉토리 data/pages/playground/
와 파일 data/pages/playground/playground.txt
이 처음에 누락 되었음을 나타냅니다 .
(rsync -rcn --out-format="%n" old/ new/ && rsync -rcn --out-format="%n" new/ old/) | sort | uniq
다음과 같은 출력을 생성합니다.
VERSION
conf/mime.conf
data/pages/playground/
data/pages/playground/playground.txt
doku.php
inc/auth.php
inc/lang/no/lang.php
lib/plugins/acl/remote.php
lib/plugins/authplain/auth.php
lib/plugins/usermanager/admin.php
rsync
이러한 인수로 실행됩니다.
-r
"디렉토리로 재귀" -c
동일한 크기의 파일을 비교하고 "mod-time & size가 아닌 checksum을 기준으로 건너 뛰기"만 -n
"변경없이 시운전을 수행"--out-format="%n"
"지정된 FORMAT을 사용하여 업데이트 출력"(여기서 파일 이름 만 "% n"임)rsync
양방향 의 출력 (파일 목록)은 을 사용하여 결합 및 정렬 된 sort
다음이 정렬 된 목록은uniq
이것은 트릭을 할 수 있습니다 :
compare_dirs()
{
# Shows which files and directories exist in one directory but not both
if [ $# -ne 2 ]
then
echo "Usage: compare_dirs dir1 dir2" >&2
return 2
fi
for path
do
if [ ! -d "$path" ]
then
echo "Not a directory: $path" >&2
return 1
fi
done
comm -3 \
<(cd -- "$1" && find . -printf '%P\0' | sort -z | quote_shell) \
<(cd -- "$2" && find . -printf '%P\0' | sort -z | quote_shell)
}
일반적으로 파일을 SubVersion 또는 git과 같은 일종의 버전 제어 시스템에 넣습니다.
그러나 dir1에서 for 루프를 사용하여 빠른 스크립트를 작성한 다음 모든 파일을 dir2의 파일과 비교할 수 있습니다. for 루프는 diff의 종료 코드를보고 파일이 다른지 알 수 있습니다.
아마도 이런 식으로 뭔가 :
for f in `(cd dir1 ; find .)`
do
diff $f ../dir2/$f
if [ "$?" == "0" ]
then
echo same
else
echo diff: $f
fi
done
참고 : 스크립트는 테스트되지 않았으므로 위 예제는 "bash inspired pseudocode"입니다.
git과 함께 또 한번 가보자
재생할 예제 파일 만들기
mkdir -p dir1/test1/test11
mkdir -p dir1/test1/test12
mkdir -p dir1/test1/test13
echo "Test1" >> dir1/test1/test11/t1.txt
echo "Test2" >> dir1/test1/test12/t2.txt
echo "Test3" >> dir1/test1/test13/t3.txt
#And a dir to work in
mkdir gitdir
그런 다음 dir을 입력하고 dir1을 가져옵니다.
cd gitdir/
git init .
cp -r ../dir1/* .
git add .
git commit -m 'dir1'
나가서 dir1을 수정하십시오 (그래서 그것은 dir2가됩니다)
cd ..
echo "Test2" > dir1/test1/test11/t1.txt
그런 다음 git dir로 이동하여 새 dir을 가져옵니다.
cd gitdir/
cp -r ../dir1/* .
이제 git에게 변경 사항을 물어보십시오 (status 명령 사용)
git status -s
출력은 다음과 같이 변경 사항이있는 목록입니다.
M test1/test11/t1.txt
이것은 rsync : 와 유사 합니다. 대상의 최신 파일을 덮어 쓸 때 표시 합니다 (중복은 아니지만 나중에 요청).
질문에 표시된 것처럼 "diff -q -r"은 유용한 처리가 필요할 수 있습니다. 질문은 출력 형식을 지정하지 않았습니다. 답변은 다양한 유형의 보고서를 제공합니다.
rsync
보다 빠르기 때문에이 목적에 유용한 도구입니다 diff
. 그러나 @nils가 제안한 솔루션은 이전 / 새 디렉토리 트리 간의 실제 차이점보다 훨씬 더 장황하고 더 많은 파일을 나열합니다. 예를 들어, 그 답변을 위해 작성한 스크립트와 동일한 데이터에서 실행하는 스크립트와 비교하면,
새 파일 을 diff
올바르게 설명 하려면 옵션도 필요합니다 (제안 된 답변에는 표시되지 않음). 그러나보다 속도가 느리기 때문에 (수십 배) 후자의 출력을 향상시키는 방법이 보인다.-N
rsync
추가 자료
나는 항상 sha1sum (또는 md5sum; 부분적으로는 안전합니다)에 부분적이었습니다.
find . -type f -print0 | xargs -0 md5sum | sort -k2 > /tmp/before
# don't miss the "sort" in there; it's important
# (later)
find . -type f -print0 | xargs -0 md5sum | sort -k2 > /tmp/after
vimdiff /tmp/before /tmp/after
# or whatever diff tool you like, even "diff -u"
때로는 이름이 바뀌거나 이동되는 파일이 너무 많은 경우와 같이 첫 번째 필드를 정렬 한 다음 diff를 수행하는 것이 도움이 될 수 있지만 대부분 충분합니다.
다른 방법들에 비해 "이전"파일의 사본을 보관할 필요가 없다는 장점이 있습니다. md5sum 출력 파일 만