Сравнить файлы в каталогах с разной структурой и показать различия (20.04)

Хотя это может звучать как задача, которую можно выполнить с помощью rsync , ] diff и тому подобное, мне не удалось добиться успеха.

AFAIK, эти инструменты учитывают структуру каталогов при сравнении файлов.

Таким образом, если «Файл A» находится в ~ / Dir-A , в то время как «Файл B» находится в ~ / Dir-B / Dir-BB , они будут обнаружены как разные файлы, даже если у них одинаковый хэш.

Требования / подробности:

  • Ubuntu 20.04
  • Сравнить Dir-A и Dir-B ;
  • Игнорировать расположение (структуру каталогов) файлы. Другими словами, мне нужно проверить только файлы, независимо от подкаталога, в котором они находятся (поэтому в приведенном выше примере файлы следует считать одинаковыми);
  • Укажите, какие файлы находятся в Dir- A и НЕ в Dir-B (и наоборот, желательно в разных списках / результатах);
  • Оба Dir-A и Dir-B имеют очень разные структуры. В некоторых случаях предполагается, что Dir-A будет иметь все, что есть в Dir-B , а также многое другое;
  • Бонус: если возможно, было бы неплохо иметь возможность чтобы проверить, есть ли в Dir-A все из нескольких других каталогов.

Подводя итог: моя конкретная ситуация включает проверку нескольких резервных копий и копий с очень разным содержанием и структурой.

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

Большое спасибо за внимание.

2
задан 4 April 2021 в 18:17

1 ответ

На самом деле я не понимаю, как это сделать без сценариев, поэтому вот короткий сценарий на Python для начала.


import hashlib
import os

def get_md5_file(filename, chunk_size=10240):
    ''' Returns md5 sum of the given filename
    '''
    md5_hash = hashlib.md5()
    with open(filename, 'rb') as f:
        while True:
            data = f.read(chunk_size)
            if not data:
                break
            
            md5_hash.update(data)
            
    digest = md5_hash.hexdigest()
    return digest

#print(get_md5('Dir-A/file1.txt'))
#print(get_md5('Dir-B/Dir-B/file1-duplicate.txt'))

def get_md5_dir(root, result=None):
    ''' Returns a dictionary with the md5 sum of every filename in directory root
    '''    
    if result is None:
        result = dict()
    
    for root, dirs, files in os.walk(root):
        for filename in files:
            filename = os.path.join(root, filename)
            md5 = get_md5_file(filename)
            if md5 in result:
                print('Warning, duplicate md5 sum', result[md5], filename)
            
            result[md5] = filename
    
    return result

if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(description='Compare directories by md5 sum')
    parser.add_argument('dirA', help='Specify first directory')
    parser.add_argument('dirB', help='Specify one or more directory to compare to',
                        nargs='+')
    args = parser.parse_args()

    # Get md5 sum for each file in dirA and each file in (possibly multiple) dirB
    md5_dirA = get_md5_dir(args.dirA)
    md5_dirB = dict()
    for root in args.dirB:
        get_md5_dir(root, md5_dirB) # update dict in place

    #print(md5_dirA)
    #print(md5_dirB)

    # print files in dirA, but not in dirB
    for md5 in md5_dirA:
        if md5 not in md5_dirB:
            print('%s (%s) not in dirB' % (md5_dirA[md5], md5))

    # print files in dirB, not in dirA
    for md5 in md5_dirB:
        if md5 not in md5_dirA:
            print('%s (%s) not in dirA' % (md5_dirB[md5], md5))
    

Для использования сохраните как текстовый файл compare_files_by_hash. py, тогда python3 compare_files_by_hash.py Dir-A Dir-B .

Бонус: если возможно, было бы неплохо иметь возможность проверить, есть ли в Dir-A все из нескольких других каталогов.

Я не уверен, что понял это, но вышеупомянутое позволяет использовать несколько каталогов Dir-B, т.е. вы можете сделать python3 compare_files_by_hash.py Dir-A Dir-B Dir-B-2 Dir-B-3 и будет так, как если бы Dir-B Dir-B-2 Dir-B-3 все были в Dir-B .

1
ответ дан 23 April 2021 в 23:26

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

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