Разница между двумя каталогами в Linux

Я пытаюсь найти файлы, существующие в одном каталоге, но не в другом, я попытался использовать эту команду:

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 в одной команде?

14 ответов


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

пояснение:

  • diff -r dir1 dir2 показывает, какие файлы находятся только в dir1 и только в dir2, а также изменения файлов, присутствующих в обоих каталогах, если таковые имеются.

  • diff -r dir1 dir2 | grep dir1 показывает, какие файлы находятся только в dir1

  • awk для печати только имени файла.


Это должно сделать работу:

diff -rq dir1 dir2

параметры объяснены (через diff (1) man page):

  • -r - рекурсивно сравните все найденные подкаталоги.
  • -q - вывод только в том случае, если файлы отличаются.

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

эта команда даст вам файлы, которые находятся в dir1 и не в директория dir2.

о <( ) знак, вы можете Google это, как подмена процесса.


хороший способ сделать это сравнение, чтобы использовать find С md5sum, потом 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/

С наилучшими пожеланиями!


Meld (http://meldmerge.org/) делает большую работу по сравнению каталогов и файлов внутри.

Meld comparing directories


vim DirDiff плагин-еще один очень полезный инструмент для сравнения каталогов.

vim -c "DirDiff dir1 dir2"

он не только перечисляет, какие файлы отличаются между каталогами, но также позволяет проверять/изменять с помощью vimdiff файлы, которые отличаются.


другой (возможно, более быстрый для больших каталогов) подход:

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

на sed команда удаляет первый компонент каталога благодаря)


Это немного поздно, но может кому-то помочь. Не уверен, что diff или rsync выплевывают только имена файлов в голом формате, как это. Спасибо plhn за предоставление этого приятного решения, которое я расширил ниже.

Если вы хотите только имена файлов, так что легко просто скопировать файлы, необходимые в чистом формате, вы можете использовать команду find.

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

предполагается, что dir1 и dir2 находятся в одной родительской папке. СЭД просто удаляет родительскую папку, чтобы вы могли сравнить яблоки с яблоками. Последний 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/'

в принятом ответе также будут перечислены файлы, которые существуют в обоих каталогах, но имеют разное содержимое. Чтобы перечислить только файлы, существующие в dir1, вы можете использовать:

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

объяснение:

  • diff-r dir1 dir2: сравнить
  • grep 'Only in': получить строки, содержащие 'Only in'
  • grep dir1: получить строки, содержащие dir

неудовлетворенный всеми ответами, так как большинство из них работают очень медленно и производят излишне длинный вывод для больших каталогов, я написал свой собственный скрипт 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

P. S. Если вам нужно сравнить размеры файлов и файлов хэши для потенциальных изменений, я опубликовал обновленный скрипт здесь: https://gist.github.com/amakukha/f489cbde2afd32817f8e866cf4abe779


упрощенный способ сравнения 2 каталогов с помощью команды DIFF

diff имя файла.1 именем.2 > имя_файла.dat > > Enter

открыть именем.dat после завершения запуска

и вы увидите: Только в имени файла.1: имя.Два Только в: directory_name: name_of_file1 Только в: directory_Name: name_of_file2


kdiff3 имеет приятный интерфейс diff для файлов и каталогов.

Проверьте URL:http://kdiff3.sourceforge.net

Он работает под Windows & Linux.


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 для выполнения строкового поиска по всей строке.


это скрипт bash для печати команд для синхронизации двух каталогов

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