Группировка файлов в одном каталоге на основе содержимого - PullRequest
0 голосов
/ 29 мая 2018

У меня есть вопрос относительно группировки файлов с одинаковым содержимым, но с разными именами файлов.Я посмотрел на filecmp.cmp(), но он сравнивает только два файла одновременно.

Идея состоит в том, чтобы превратить что-то вроде этого:

file1: [a,b,c,d,e,f,g,h,i]
file2: [a,b,c,d,e,f,g,h,i]
file3: [a,b,c,d,e,f,g,h,i]
file4: [a,b,c,d,e,f,g,h]
file5: [a,b,c,d,e,f,g,h]
file6: [a,b,c,d,e]

В:

file(1,2,3): [a,b,c,d,e,f,g,h,i]
file(4,5): [a,b,c,d,e,f,g,h]
file(6): [a,b,c,d,e]

Я думаю, что у меня есть около 1800 файлов .txt, но только около 20 уникальных файлов.Я хочу создать список, или словарь, или фрейм данных, который показывает группировку.

Любая помощь приветствуется.Спасибо!

Ответы [ 3 ]

0 голосов
/ 29 мая 2018

Предположим, у вас есть 6 файлов, расположенных как

- my_files/
    - file1.txt
    - file2.txt
    - file3.txt
    - file4.txt
    - file5.txt
    - file6.txt

Затем вы можете прочитать их как строки и использовать pandas, чтобы сделать всю работу за вас

with open("my_files/file1.txt"),
     open("my_files/file2.txt"),
     open("my_files/file3.txt"),
     open("my_files/file4.txt"),
     open("my_files/file5.txt"),
     open("my_files/file6.txt") as file1, file2, file3, file4, file5, file6:


     df = pd.DataFrame({"values": [file1.read(), file2.read(), file3.read(), 
                          file4.read(), file5.read(), file6.read()], 
                        "f":["file1", "file2", "file3", "file4", "file5", "file6"]})

Использование groupby:

>>> df.groupby("values", as_index=False).agg({"f": ",".join})

    values                f
0   [a,b,c,d,e,f,g,h,i]   file1,file2,file3
1   [a,b,c,d,e,f,g,h]     file4,file5
2   [a,b,c,d]             file6
0 голосов
/ 29 мая 2018

Классическим способом было бы использование словарей.Сначала составьте список всех имен файлов в каталоге и сохраните его в списке с именем file_names.Тогда:

filedict={}
for name in file_names:
    file=open(name,"r")
    filecontents=file.read()
    if filecontents in filedict:
        filedict[filecontents].append(name)
    else:
        filedict[filecontents]=[]
        filedict[filecontents].append(name)

Каждое значение этого словаря будет списком файлов с одинаковым текстовым содержимым.Ключи словаря будут строкой файла.

0 голосов
/ 29 мая 2018

Вы можете использовать хеш-функцию, например SHA-1, для проверки файлов с одинаковым содержимым, вот выдержка из этого источника :

import hashlib
BLOCKSIZE = 65536

def hash_value_for(file_name):
  hasher = hashlib.sha1()
  with open(file_name, 'rb') as afile:
      buf = afile.read(BLOCKSIZE)
      while len(buf) > 0:
          hasher.update(buf)
          buf = afile.read(BLOCKSIZE)

  return hasher.hexdigest()

Например, вышеуказанная функция, если имя файла вернет хеш-значение его содержимого.

file1.txt

Это тест.

file2.txt

Это тест!

file3.txt

Это тест.

Вывод:

print(hash_value_for("file1.txt"))
> 0828324174b10cc867b7255a84a8155cf89e1b8b
print(hash_value_for("file2.txt"))
> cc4bc53ee478380f385721b45247107338a9cec3
print(hash_value_for("file3.txt"))
> 0828324174b10cc867b7255a84a8155cf89e1b8b

Теперь вернемся к исходному примеру:

Файлы:

Предполагается, что у нас есть следующие файлы со следующим содержимым для каждого:

file1: [a,b,c,d,e,f,g,h,i]
file2: [a,b,c,d,e,f,g,h,i]
file3: [a,b,c,d,e,f,g,h,i]
file4: [a,b,c,d,e,f,g,h]
file5: [a,b,c,d,e,f,g,h]
file6: [a,b,c,d,e]

Код:

import hashlib
import itertools

BLOCKSIZE = 65536


def hash_value_for(file_name):
    hasher = hashlib.sha1()
    with open(file_name, 'rb') as afile:
        buf = afile.read(BLOCKSIZE)
        while len(buf) > 0:
            hasher.update(buf)
            buf = afile.read(BLOCKSIZE)

    return hasher.hexdigest()


file_names = ["file1.txt", "file2.txt", "file3.txt",
              "file4.txt", "file5.txt", "file6.txt"]

file_names_with_hash_values = {}
for file_name in file_names:
    file_names_with_hash_values[file_name] = hash_value_for(file_name)

result = {}
for key, value in sorted(file_names_with_hash_values.items()):
    result.setdefault(value, []).append(key)

print(result)

Вывод:

{'e99a894b164a9274e7dabc1b77b41f4148860d96': ['file1.txt', 'file2.txt', 'file3.txt'], 
'bf141159c6499f26f46c7bdc28914417ff66aa15': ['file4.txt', 'file5.txt'], 
'a019bdc760a550cdc55de1343d4ebbcff1ba49c3': ['file6.txt']}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...