Różnica między dwoma katalogami w Linuksie

Próbuję znaleźć pliki istniejące w jednym katalogu, ale nie w drugim, próbowałem użyć tego polecenia:

diff -q dir1 dir2

Problem z powyższym poleceniem, że znajduje zarówno pliki w dir1, ale nie w dir2, jak i pliki w dir2, ale nie w dir1,

Próbuję znaleźć pliki w dir1, ale nie tylko w dir2.

Oto mała próbka moich danych

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

Kolejnym pytaniem w mojej głowie jest jak mogę znaleźć pliki w dir1 ale nie w dir2 lub dir3 w jednym poleceniu?

Author: codeforester, 2013-05-28

14 answers

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

Explanation:

  • diff -r dir1 dir2 pokazuje, które pliki są tylko w dir1, a te tylko w dir2, a także zmiany plików obecnych w obu katalogach, jeśli istnieją.

  • diff -r dir1 dir2 | grep dir1 pokazuje, które pliki są tylko w dir1

  • awk aby wydrukować tylko nazwę pliku.

 317
Author: asclepix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-26 12:41:41

To powinno wystarczyć:

diff -rq dir1 dir2

Opcje wyjaśnione(za pomocą strony man diff (1) ):

  • -r - rekurencyjnie porównuje znalezione podkatalogi.
  • -q - wypisuje tylko, czy Pliki się różnią.
 87
Author: tokhi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-27 11:00:39
comm -23 <(ls dir1 |sort) <(ls dir2|sort)

To polecenie da ci pliki, które są w dir1 i , a nie w dir2.

O podpisie <( ) możesz go wygooglować jako "substytucję procesu".

 44
Author: plhn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-04 15:56:40

Dobrym sposobem na to porównanie jest użycie find z md5sum, a następnie diff.

Przykład:

Użyj find, Aby wyświetlić listę wszystkich plików w katalogu, a następnie Oblicz Skrót md5 dla każdego pliku i prześlij go do pliku:

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

Wykonaj tę samą procedurę do innego katalogu:

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

Następnie porównaj wynik dwóch plików z "diff":

diff dir1.txt dir2.txt

Ta strategia jest bardzo przydatna, gdy dwa katalogi do porównania nie są w tej samej maszynie i musisz się upewnić że pliki są równe w obu katalogach.

Innym dobrym sposobem na wykonanie zadania jest użycie git

git diff --no-index dir1/ dir2/
Pozdrawiam!
 18
Author: Adail Junior,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-07 00:49:13

Meld ( http://meldmerge.org/) wykonuje świetną robotę przy porównywaniu katalogów i plików wewnątrz.

Meldowanie katalogów

 10
Author: Catalin Hritcu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-04 17:02:51

Wtyczka Vima DirDiff jest kolejnym bardzo przydatnym narzędziem do porównywania katalogów.

vim -c "DirDiff dir1 dir2"

Nie tylko wymienia, które Pliki różnią się między katalogami, ale także pozwala sprawdzić/zmodyfikować za pomocą vimdiff pliki, które są różne.

 10
Author: drrossum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-08 22:49:00

Inne (może szybsze dla dużych katalogów) podejście:

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

Polecenie sed usuwa pierwszy składnik katalogu dzięki postowi Erika)

 5
Author: jaltek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:31

Trochę za późno, ale może komuś pomóc. Nie wiem, czy diff lub rsync wypluwają tylko nazwy plików w takim gołym formacie. Dzięki plhn za to miłe rozwiązanie, które rozszerzyłem poniżej.

Jeśli chcesz tylko nazwy plików, aby łatwo było skopiować potrzebne pliki w czystym formacie, możesz użyć polecenia Znajdź.

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

Zakłada się, że zarówno dir1, jak i dir2 znajdują się w tym samym folderze nadrzędnym. sed po prostu usuwa folder nadrzędny, dzięki czemu można porównać jabłka z jabłkami. Ostatni sed przywraca nazwę dir1.

Jeśli chcesz tylko pliki:

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

Podobnie dla katalogów:

comm -23 <(find dir1 -type d | sed 's/dir1/\//'| sort) <(find dir2 -type d | sed 's/dir2/\//'| sort) | sed 's/^\//dir1/'
 4
Author: James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-14 13:27:50

Przyjęta odpowiedź wyświetli również listę plików, które istnieją w obu katalogach, ale mają inną zawartość. Aby wyświetlić listę tylko plików, które istnieją w dir1, możesz użyć:

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

Wyjaśnienie:

  • diff-r dir1 dir2: compare
  • grep 'Only in': pobiera linie zawierające 'Only in'
  • grep dir1: pobiera linie zawierające katalog
 4
Author: Aris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-28 16:35:39

Niezadowolony ze wszystkich odpowiedzi, ponieważ większość z nich działa bardzo powoli i generuje niepotrzebnie długie wyjście dla dużych katalogów, napisałem własny skrypt Pythona, aby porównać dwa foldery.

W przeciwieństwie do wielu innych rozwiązań, nie porównuje zawartości plików. Ponadto nie wchodzi do podkatalogów, których brakuje w innym katalogu. Tak więc wyjście jest dość zwięzłe, a skrypt działa szybko.

#!/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])

Przykładowe użycie:

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

Lub jeśli chcesz zobaczyć tylko pliki z pierwszego katalogu:

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

P. S. jeśli chcesz porównać rozmiary plików i skróty plików pod kątem potencjalnych zmian, opublikowałem zaktualizowany skrypt tutaj: https://gist.github.com/amakukha/f489cbde2afd32817f8e866cf4abe779

 4
Author: Ohne Kleidung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-09 06:43:31

Uproszczony sposób porównywania 2 katalogów za pomocą polecenia DIFF

Nazwa pliku Diff.1 nazwa pliku.2 > nazwa pliku.dat > > Enter

Otwórz nazwę pliku.dat po zakończeniu biegu

I zobaczysz: Tylko w nazwie pliku.1: nazwa pliku.2 Tylko w: directory_name: name_of_file1 Tylko w: directory_Name: name_of_file2

 0
Author: nerakk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-25 14:59:34

Kdiff3 ma ładny interfejs diff dla plików i katalogów.

Sprawdź URL: http://kdiff3.sourceforge.net

Działa pod Windows i Linux.

 0
Author: ayakout,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-03 09:02:52

GNU grep może odwrócić wyszukiwanie za pomocą opcji -v. To sprawia, że grep zgłasza linie, które nie pasują. Dzięki temu możesz usunąć pliki w dir2 z listy plików w dir1.

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

Opcje -F -x mówią grep, Aby wykonać wyszukiwanie ciągu znaków na całej linii.

 0
Author: ceving,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-09 07:21:36

Jest to skrypt bash do drukowania poleceń do synchronizacji dwóch katalogów

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
Author: Ebru Yener,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-07 22:27:27