Сравнение содержимого двух каталогов

Notify-OSD не разрешает настройку по умолчанию (крайне неприятно, что я знаю), но это так по дизайну. Вам нужно будет использовать другой метод уведомления для получения того же позиционирования и других параметров.

1
задан 28 April 2015 в 02:53

8 ответов

Вы можете использовать команду diff так же, как использовать ее для файлов:

diff <directory1> <directory2>

Если вы хотите видеть вложенные папки и файлы, вы можете использовать опцию -r:

diff -r <directory1> <directory2>
51
ответ дан 24 May 2018 в 11:44
  • 1
    Не знал, что diff работает и для каталогов (man diff подтвердил это), но это не рекурсивно проверяет изменения в подкаталогах внутри подкаталогов. – jobin 16 February 2014 в 23:04
  • 2
    @Jobin Это странно ... Для меня это работает. – Alex R. 16 February 2014 в 23:07
  • 3
    У меня есть что-то вроде этого: a/b/c/d/a, x/b/c/d/b. Посмотрите, что дает вам diff a x. – jobin 16 February 2014 в 23:09
  • 4
    Вы должны использовать опцию -r. Это (diff -r a x) дает мне: Only in a/b/c/d: a. only in x/b/c/d: b. – Alex R. 16 February 2014 в 23:11
  • 5
    diff показывает мне разницу в файлах INTO, но не в том случае, если каталог содержит файл, который не содержит другой. Мне не нужно знать различия в файле, но также, если файл существует в каталоге, а не в другом – AndreaNobili 16 February 2014 в 23:17

Вот альтернатива, чтобы сравнить только имена файлов, а не их содержимое:

diff <(cd folder1 && find . | sort) <(cd folder2 && find . | sort)

Это простой способ перечислить недостающие файлы, но, конечно, он не будет обнаруживать файлы с одинаковыми имя, но различное содержимое!

(Лично я использую свой собственный скрипт diffdirs, но это часть большей библиотеки.)

13
ответ дан 24 May 2018 в 11:44
  • 1
    Вам лучше использовать замену процессов, а не временные файлы ... – mniip 17 February 2014 в 00:03
  • 2
    Хорошее предложение, спасибо. – joeytwiddle 17 February 2014 в 11:16
  • 3
    Обратите внимание, что это не поддерживает имена файлов с определенными специальными символами, в этом случае вы можете использовать нулевые разделители, которые AFAIK diff не поддерживает на данный момент. Но есть comm, который поддерживает его с git.savannah.gnu.org/cgit/coreutils.git/commit/… , поэтому, когда дело доходит до ближайшего к вам ядра, вы можете сделать [ f3] (выход которого вам, возможно, придется преобразовать в нужном формате, используя параметр --output-delimiter и дополнительные инструменты). – phk 6 March 2016 в 01:52

Вы не можете использовать bash, вы можете сделать это с помощью diff с --brief и --recursive:

$ diff -rq dir1 dir2 
Only in dir2: file2
Only in dir1: file1

В man diff включены обе опции:

-q, --brief сообщают только, когда файлы отличаются -r, --recursive рекурсивно сравнивать любые найденные подкаталоги
11
ответ дан 24 May 2018 в 11:44

Если вы хотите сделать каждый файл расширяемым и сворачиваемым, вы можете передать вывод diff -r в Vim.

Сначала дадим Vim правило сгибания:

mkdir -p ~/.vim/ftplugin
echo "set foldexpr=getline(v:lnum)=~'^diff.*'?'>1':1 foldmethod=expr fdc=2" >> ~/.vim/ftplugin/diff.vim
[d3 ] Теперь просто:

diff -r dir1 dir2 | vim -

Вы можете нажать zo и zc, чтобы открыть и закрыть складки. Чтобы выбраться из Вима, нажмите :q<Enter>

3
ответ дан 24 May 2018 в 11:44

Довольно простая задача для достижения в python:

python -c 'import os,sys;d1=os.listdir(sys.argv[1]);d2=os.listdir(sys.argv[2]);d1.sort();d2.sort();x="SAME" if d1 == d2 else "DIFF";print x' DIR1 DIR2

Заменить фактические значения для DIR1 и DIR2.

Вот пример:

$ python -c 'import os,sys;d1=os.listdir(sys.argv[1]);d2=os.listdir(sys.argv[2]);d1.sort();d2.sort();x="SAME" if d1 == d2 else "DIFF";print x' Desktop/ Desktop
SAME
$ python -c 'import os,sys;d1=os.listdir(sys.argv[1]);d2=os.listdir(sys.argv[2]);d1.sort();d2.sort();x="SAME" if d1 == d2 else "DIFF";print x' Desktop/ Pictures/
DIFF

Для удобства чтения здесь вместо скрипта используется реальный скрипт:

#!/usr/bin/env python
import os, sys

d1 = os.listdir(sys.argv[1])
d2 = os.listdir(sys.argv[2])
d1.sort()
d2.sort()

if d1 == d2:
    print("SAME")
else:
    print("DIFF")
2
ответ дан 24 May 2018 в 11:44
  • 1
    Обратите внимание, что os.listdir не дает никакого конкретного порядка. Таким образом, списки могут иметь одинаковые вещи в разном порядке, и сравнение не получится. – muru 14 November 2016 в 10:15
  • 2
    @muru хорошая точка, я буду включать сортировку к тому – Sergiy Kolodyazhnyy 14 November 2016 в 10:17

Возможно, один из вариантов заключается в том, чтобы запустить rsync два раза

rsync -r -n -t -v --progress -c -s /dir1/ /dir2/

С предыдущей строкой вы получите файлы, которые находятся в каталоге dir1 и отличаются (или отсутствуют) в каталоге dir2. Кроме того, папки с другой датой.

rsync -r -n -t -v --progress -c -s /dir2/ /dir1/

То же самое для dir2

#from the rsync --help :
-r, --recursive             recurse into directories
-n, --dry-run               perform a trial run with no changes made
-t, --times                 preserve modification times
-v, --verbose               increase verbosity
    --progress              show progress during transfer
-c, --checksum              skip based on checksum, not mod-time & size
-s, --protect-args          no space-splitting; only wildcard special-chars

Вы можете удалить параметр -n, чтобы претерпеть изменения. Это копирование списка файлов во вторую папку. Если вы это сделаете, возможно, хороший вариант - использовать -u, чтобы не перезаписывать более новые файлы.

-u, --update                skip files that are newer on the receiver
1
ответ дан 24 May 2018 в 11:44

Вдохновленный ответом Сергея, я написал собственный скрипт 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])

Если вы сохраните его в файле с именем compare_dirs.py, вы можете запустить его с помощью Python3.x:

python3 compare_dirs.py dir1 dir2

Пример вывода:

user@laptop:~$ python3 compare_dirs.py old/ new/
DIR  old/out/flavor-domino removed
DIR  new/out/flavor-maxim2 added
DIR  old/target/vendor/flavor-domino removed
DIR  new/target/vendor/flavor-maxim2 added
FILE old/tmp/.kconfig-flavor_domino removed
FILE new/tmp/.kconfig-flavor_maxim2 added
DIR  new/tools/tools/LiveSuit_For_Linux64 added
1
ответ дан 24 May 2018 в 11:44

Я добавлю в этот список альтернативу NodeJs, которую я написал некоторое время назад.

dir-compare

npm install dir-compare -g
dircompare dir1 dir2
0
ответ дан 24 May 2018 в 11:44

Другие вопросы по тегам:

Похожие вопросы: