한 디렉토리에는 있지만 다른 디렉토리에는없는 파일을 찾으십시오.


295

한 디렉토리에 존재하지만 다른 디렉토리에는없는 파일을 찾으려고 노력 중입니다.이 명령을 사용하려고했습니다.

diff -q dir1 dir2

이 두 파일을 발견 한 위의 명령의 문제에서 dir1가 아니라에서 dir2뿐만 아니라 파일과에서 dir2가 아니라에서 dir1,

나는 파일을 찾으려고 노력하고 있지만 그 안에있는 dir1것이 아닙니다 dir2.

다음은 내 데이터가 어떻게 보이는지에 대한 작은 샘플입니다.

dir1    dir2    dir3
1.txt   1.txt   1.txt
2.txt   3.txt   3.txt
5.txt   4.txt   5.txt
6.txt   7.txt   8.txt

내 마음에 또 다른 질문은 파일을 찾을 수는 dir1있지만 단일 명령으로 dir2또는 dir3단일 명령으로 어떻게 찾을 수 있습니까?

답변:


390
diff -r dir1 dir2 | grep dir1 | awk '{print $4}' > difference1.txt

설명:

  • diff -r dir1 dir2 dir1에만있는 파일과 dir2에만있는 파일 및 두 디렉토리에있는 파일의 변경 사항도 표시합니다 (있는 경우).

  • diff -r dir1 dir2 | grep dir1 dir1에만있는 파일을 표시합니다

  • awk 파일 이름 만 인쇄합니다.


5
나는 grepsth ^dir1를 위해 dir1나중에 길에 나타나지 않도록 하고 싶습니다 .
Alfe

@Alfe 그것은 향상 될 수 있습니다. 나는 $4예로서 사용 합니다. 사실, 내 실제 우분투 diff에서 이탈리아어로 답장합니다. $4이탈리아어 및 영어 답글에 대해서는 괜찮지 만 다른 모든 언어에 대해서는 잘 모르겠습니다 ...
asclepix

139

이것은 일을해야합니다 :

diff -rq dir1 dir2

옵션 설명 (diff (1) 매뉴얼 페이지를 통해 ) :

  • -r -발견 된 서브 디렉토리를 재귀 적으로 비교하십시오.
  • -q -파일이 다른지 여부 만 출력합니다.

8
좋은! 그러나 나는 그것이 그렇게 확장되어야한다고 생각한다 :diff -rq dir1 dir2 | grep 'Only in dir1/'
sobi3ch

2
이는 내용을 비교 한 것으로 느린 드라이브에서는 시간이 오래 걸릴 수 있습니다.
Smeterlink

5
-q옵션 에 대한 참고 사항 : 매뉴얼 페이지에는 파일이 다른지 확인하는 방법이 아니라 "파일이 다른지 여부 만 출력"만 표시됩니다. 소스 코드를 익히고 실제 크기가 아닌 차이점을 확인하기 위해 파일 크기 만 확인한다는 것을 알았습니다.
ryancdotnet 2016 년

-q옵션에 관해서는 파일 크기 만 확인한다는 것을 재현 할 수 없습니다. GNU Diffutils 3.7을 사용하여 파일 크기는 같지만 diff -q file1 file2출력 내용이 다른 두 파일을 비교 합니다 Files file1 and file2 differ.
Stefan Schmidt

50
comm -23 <(ls dir1 |sort) <(ls dir2|sort)

이 명령은 dir2가 아닌 dir1에있는 파일을 제공합니다 .

정보 <( )기호, 당신은 '공정 대체'로 구글 수 있습니다.


내가 생각하기에, 또한 하위 디렉토리와 함께 작동하도록 잘 될 것 (ls -R dir1|sort)트릭을 할 수
ulkas

1
이것은 OS X 복구 모드에서 작동합니다.
Anthony Vanover

@ulkas,를 사용하면 출력이 올바르지 않을 수 있습니다 (ls -R dir|sort).
Andriy Makukha

3
vimdiff는 색상 강조 표시와 훨씬 더 나은 시각적 비교를 제공합니다.vimdiff <(ls dir1 |sort) <(ls dir2|sort)
Logan Reed

32

이 비교를 할 수있는 좋은 방법은 사용하는 것입니다 findmd5sum다음, diff.

예:

를 사용하여 find디렉토리의 모든 파일 목록은 다음 파일에 각 파일 및 파이프를위한 MD5 해시를 계산 :

find /dir1/ -type f -exec md5sum {} \; > dir1.txt

다른 디렉토리와 동일한 절차를 수행하십시오.

find /dir2/ -type f -exec md5sum {} \; > dir2.txt

그런 다음 결과 두 파일을 "diff"와 비교하십시오.

diff dir1.txt dir2.txt

이 전략은 비교할 두 디렉토리가 동일한 시스템에 있지 않고 두 디렉토리에서 파일이 동일한 지 확인해야 할 때 매우 유용합니다.

작업을 수행하는 또 다른 좋은 방법은 git을 사용하는 것입니다.

git diff --no-index dir1/ dir2/

친애하는!


1
나는 git repo 안에없는 임의의 디렉토리에서 diff를 할 수있는 git 가지 않았다 ... 이 답변은 방금 큰 문제를 해결했습니다. 감사합니다
ViktorNova

17

Meld ( http://meldmerge.org/ )는 디렉토리와 파일을 비교하는 데 큰 역할을합니다.

녹는 디렉토리 비교


멜딩을 제외하고 줄 끝
0xC0000022L

1
줄 끝에 문제가 없었습니다. 자세히 설명해 주시겠습니까?
Catalin Hritcu

예, 그것은하지 않습니다 나타내는 라인 엔딩. 이로 인해이 도구를 사용하는 개발자들은 예를 들어 CRLF를 CRLFLF로 만들어 줄 끝을 "고정한"변경 사항을 커밋했습니다.
0xC0000022L

3
또한 파일 내용 읽기를 요구하므로 >> 1GB 디렉토리에서는 거의 쓸모가 없습니다.
Tomislav Nakic-Alfirevic

13

vim의 DirDiff 플러그인은 디렉토리를 비교하는 데 유용한 또 다른 도구입니다.

vim -c "DirDiff dir1 dir2"

디렉토리간에 다른 파일을 나열 할뿐만 아니라 vimdiff를 사용하여 다른 파일을 검사 / 수정할 수도 있습니다.


11

모든 답글에 만족하지 못했습니다. 대부분이 매우 느리게 작동하고 큰 디렉토리에 대해 불필요하게 긴 출력을 생성하기 때문에 두 폴더를 비교하기 위해 자체 Python 스크립트를 작성했습니다.

다른 많은 솔루션과 달리 파일의 내용을 비교하지 않습니다. 또한 다른 디렉토리에없는 하위 디렉토리에 들어 가지 않습니다. 따라서 출력이 매우 간결하고 스크립트가 빠르게 작동합니다.

#!/usr/bin/env python3

import os, sys

def compare_dirs(d1: "old directory name", d2: "new directory name"):
    def print_local(a, msg):
        print('DIR ' if a[2] else 'FILE', a[1], msg)
    # ensure validity
    for d in [d1,d2]:
        if not os.path.isdir(d):
            raise ValueError("not a directory: " + d)
    # get relative path
    l1 = [(x,os.path.join(d1,x)) for x in os.listdir(d1)]
    l2 = [(x,os.path.join(d2,x)) for x in os.listdir(d2)]
    # determine type: directory or file?
    l1 = sorted([(x,y,os.path.isdir(y)) for x,y in l1])
    l2 = sorted([(x,y,os.path.isdir(y)) for x,y in l2])
    i1 = i2 = 0
    common_dirs = []
    while i1<len(l1) and i2<len(l2):
        if l1[i1][0] == l2[i2][0]:      # same name
            if l1[i1][2] == l2[i2][2]:  # same type
                if l1[i1][2]:           # remember this folder for recursion
                    common_dirs.append((l1[i1][1], l2[i2][1]))
            else:
                print_local(l1[i1],'type changed')
            i1 += 1
            i2 += 1
        elif l1[i1][0]<l2[i2][0]:
            print_local(l1[i1],'removed')
            i1 += 1
        elif l1[i1][0]>l2[i2][0]:
            print_local(l2[i2],'added')
            i2 += 1
    while i1<len(l1):
        print_local(l1[i1],'removed')
        i1 += 1
    while i2<len(l2):
        print_local(l2[i2],'added')
        i2 += 1
    # compare subfolders recursively
    for sd1,sd2 in common_dirs:
        compare_dirs(sd1, sd2)

if __name__=="__main__":
    compare_dirs(sys.argv[1], sys.argv[2])

샘플 사용법 :

user@laptop:~$ python3 compare_dirs.py dir1/ dir2/
DIR  dir1/out/flavor-domino removed
DIR  dir2/out/flavor-maxim2 added
DIR  dir1/target/vendor/flavor-domino removed
DIR  dir2/target/vendor/flavor-maxim2 added
FILE dir1/tmp/.kconfig-flavor_domino removed
FILE dir2/tmp/.kconfig-flavor_maxim2 added
DIR  dir2/tools/tools/LiveSuit_For_Linux64 added

또는 첫 번째 디렉토리의 파일 만 보려면 :

user@laptop:~$ python3 compare_dirs.py dir2/ dir1/ | grep dir1
DIR  dir1/out/flavor-domino added
DIR  dir1/target/vendor/flavor-domino added
FILE dir1/tmp/.kconfig-flavor_domino added

추신 : 잠재적 변경 사항에 대해 파일 크기와 파일 해시를 비교 해야하는 경우 https://gist.github.com/amakukha/f489cbde2afd32817f8e866cf4abe779에 업데이트 된 스크립트를 게시했습니다.


내가 원하는 것을 정확하게 수행하는 간단한 스크립트 : 대량 사본 확인 : +1 (python2로 변환해야 함) 힌트 : 집합을 사용하면 diff 부분이 더 단순해질 수 있습니다.
Jason Morgan

6

또 다른 (큰 디렉토리의 경우 더 빠를 수도 있음) 접근법 :

$ find dir1 | sed 's,^[^/]*/,,' | sort > dir1.txt && find dir2 | sed 's,^[^/]*/,,' | sort > dir2.txt
$ diff dir1.txt dir2.txt

sed명령은 Erik`s post 덕분에 첫 번째 디렉토리 구성 요소를 제거합니다 )


1
나는이 방법이 더 간단하다고 생각합니다 (여전히 find주석을 사용 하고 별도의 대답 은 사용 하지 마십시오) : cd dir2; find . -exec [ -e ../dir1/{} ] \; -o -print 2>/dev/null 이것은 dir2에는 있지만 dir1에는없는 파일을 인쇄합니다.
Alexander Amelkin

5

조금 늦었지만 누군가를 도울 수 있습니다. diff 또는 rsync가 파일 이름을 이와 같은 베어 형식으로 뱉어 낼지 확실하지 않습니다. 아래에서 확장 된 멋진 솔루션을 제공 한 plhn에게 감사드립니다.

파일 이름 만 원하면 깔끔한 형식으로 필요한 파일을 쉽게 복사 할 수 있습니다. find 명령을 사용할 수 있습니다.

comm -23 <(find dir1 | sed 's/dir1/\//'| sort) <(find dir2 | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'

이는 dir1과 dir2가 모두 동일한 상위 폴더에 있다고 가정합니다. sed는 부모 폴더를 제거하여 사과와 사과를 비교할 수 있습니다. 마지막 sed는 dir1 이름을 다시 넣습니다.

파일 만 원하는 경우 :

comm -23 <(find dir1 -type f | sed 's/dir1/\//'| sort) <(find dir2 -type f | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'

디렉토리와 유사하게 :

comm -23 <(find dir1 -type d | sed 's/dir1/\//'| sort) <(find dir2 -type d | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'

1
예를 들어, 을 사용 cd하는 find대신 이전에 수행 할 수 있습니다. ( s는 현재 디렉토리를 사용 하지 못하게하기 위해 여기에 있습니다.)sedcomm -23 <(cd dir1 || exit; find -type f | sort) <(cd dir2 || exit; find -type f | sort)exitfindcd
phk

또한 특정 특수 문자가있는 파일이 있으면 솔루션이 실패 할 수 있습니다. 최신 버전의 comm지원 -z( git.savannah.gnu.org/cgit/coreutils.git/commit/…으로 제공 )을 사용하면 수행 할 수 있습니다 comm -23 -z <(cd dir1 && find -type f -print0 | sort -z) <(cd dir2 && find -type f -print0 | sort -z). (그동안 나는 또한 exits를 교체 할 수 있음을
알았습니다

5

허용되는 답변에는 두 디렉토리에 모두 존재하지만 내용이 다른 파일이 나열됩니다. dir1에 존재하는 파일 만 나열하려면 다음을 사용할 수 있습니다.

diff -r dir1 dir2 | grep 'Only in' | grep dir1 | awk '{print $4}' > difference1.txt

설명:

  • diff -r dir1 dir2 : 비교
  • grep 'Only in': 'Only in'이 포함 된 줄을 가져옵니다.
  • grep dir1 : dir을 포함하는 줄을 얻는다

5

이 답변은 -D옵션 을 추가하여 @ Adail-Junior의 제안 중 하나를 최적화합니다.이 옵션은 비교되는 디렉토리가 git 저장소가 아닌 경우에 유용합니다.

git diff -D --no-index dir1/ dir2/

사용하면 -D다음과 비교할 수 없습니다 /dev/null. text Binary files a/whatever and /dev/null differ


두 디렉토리를 비교하는 데 매우 유용했으며 파일 간의 차이점을 즉시 알 수 있습니다. 물론 텍스트 내용이있는 파일에서 가장 잘 작동합니다.
Erich Kuester

1

DIFF 명령을 사용하여 2 개의 디렉토리를 비교하는 간단한 방법

diff filename.1 filename.2> filename.dat >> 입력

실행이 완료된 후 filename.dat를여십시오.

다음과 같이 표시됩니다 : filename.1에만 : filename.2에만 : directory_name : name_of_file1에만 : directory_Name : name_of_file2


왜 .dat 파일로 출력해야합니까?
Vishnu NK

1

이것은 두 디렉토리를 동기화하기위한 명령을 인쇄하는 bash 스크립트입니다

dir1=/tmp/path_to_dir1
dir2=/tmp/path_to_dir2
diff -rq $dir1 $dir2 | sed -e "s|Only in $dir2\(.*\): \(.*\)|cp -r $dir2\1/\2 $dir1\1|" |  sed -e "s|Only in $dir1\(.*\): \(.*\)|cp -r $dir1\1/\2 $dir2\1|" 

0

GNU grep는 옵션을 사용하여 검색을 반대로 할 수 있습니다 -v. 이렇게하면 grep일치하지 않는 행 을 보고합니다. 이를 통해의 파일 dir2목록에서 파일을 제거 할 수 있습니다 dir1.

grep -v -F -x -f <(find dir2 -type f -printf '%P\n') <(find dir1 -type f -printf '%P\n')

옵션은 -F -x말할 grep전체 라인의 문자열 검색을 수행 할 수 있습니다.

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