리눅스 diff 도구 : 수정 된 파일 목록 만들기


14

Linux 명령 줄 도구를 사용하여 프로그래밍 방식으로 수정 된 파일 목록을 작성하는 방법은 무엇입니까? 특정 파일 (델타, 패치)의 차이점에 관심이 없습니다. 이전 제품 릴리스와 비교하여 새 파일 또는 수정 된 파일 목록을 원합니다. 새 제품 업데이트를 게시 할 수 있습니다.

업데이트 : diff -qr매우 편리한 출력을 생성하지 않습니다. 출력 diff -qr도 처리해야합니다. 더 좋은 방법이 있습니까?


"편리한"출력의 예는 무엇입니까?
frogstarr78

답변:


8

나는 이것을위한 간단한 접근법을 가지고있다 : rsync-preview 모드를 사용하십시오 :

rsync -aHSvn --delete old_dir/ new-dir/

해당 명령에 의해 "삭제됨"으로 표시되는 파일은 "새"파일이됩니다. 전송 될 다른 것들은 어떤 식 으로든 변경되었습니다. 자세한 내용은 rsync-man-page를 참조하십시오.


13

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 도구를 사용하여 비교해야했습니다. 가는 유일한 방법 인 것 같습니다…
Hi-Angel

3

diffutils패키지는 포함 lsdiff도구를. diff -ulsdiff에 출력을 전달하십시오 .

diff -u --other-diff-options path1 path2 | lsdiff

좋은 제안, 감사합니다. patchutils나를 위해 패키지에 있었습니다 (CentOS 5.x).
Steve Kehlet

그렇습니다. Ubuntu / Debian 용 patchutils 패키지도 있습니다.
artfulrobot

1

업데이트 할 때마다 파일을 터치하면 그 이후로 수정 된 파일을 찾을 수 있습니다 find /tree/location -newer /last/update/file -print


1

변경된 파일 이름 만 사용하려면 다음 명령을 사용하십시오.

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/'

1

프로그래밍 방식으로 새 파일 또는 수정 된 파일 목록을 만들려면 rsync , sortuniq을 사용하는 것이 가장 좋습니다 .

(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


0

다음을 사용하여 원하는 결과를 얻을 수 있습니다.

diff -r --brief dir1/ dir2/

0

이것은 트릭을 할 수 있습니다 :

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)
}

0

일반적으로 파일을 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

0

아마도 당신은 다른 무언가로 더 행복 할 것입니다. 시도하십시오 git.

예를 들어이 작업을 수행하십시오.

mkdir a
cd a
git init
touch b
git add . && git commit -m "Empty file"
git status
echo c >> b
git status
git add . && git commit -m "Full file"
git status

git당신을 위해 파일을 추적합니다. 이 명령 git status은 마지막 커밋 이후 수정 된 모든 파일을 보여줍니다.


0

이것은 rsync : 와 유사 합니다. 대상의 최신 파일을 덮어 쓸 때 표시 합니다 (중복은 아니지만 나중에 요청).

질문에 표시된 것처럼 "diff -q -r"은 유용한 처리가 필요할 수 있습니다. 질문은 출력 형식을 지정하지 않았습니다. 답변은 다양한 유형의 보고서를 제공합니다.

rsync보다 빠르기 때문에이 목적에 유용한 도구입니다 diff. 그러나 @nils가 제안한 솔루션은 이전 / 새 디렉토리 트리 간의 실제 차이점보다 훨씬 더 장황하고 더 많은 파일을 나열합니다. 예를 들어, 그 답변을 위해 작성한 스크립트와 동일한 데이터에서 실행하는 스크립트와 비교하면,

  • @nils 답변은 605 줄을 생성합니다 (명백히 디렉토리 변경 사항 이 포함되어 있기 때문에 )
  • "diff -q -r"은 몇 분 동안 실행 한 후 352 줄을 생성합니다.
  • 내 스크립트는 252 줄을 보여줍니다 ( 실제 파일 변경, 추가 또는 삭제)

파일 을 diff올바르게 설명 하려면 옵션도 필요합니다 (제안 된 답변에는 표시되지 않음). 그러나보다 속도가 느리기 때문에 (수십 배) 후자의 출력을 향상시키는 방법이 보인다.-Nrsync

추가 자료


0

나는 항상 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 출력 파일 만

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.