Python:为文件列表构建唯一的文件名

时间:2016-01-29 14:11:24

标签: python

我正在使用许多非常大的文件(例如1000 x 512MB),我实现了一种通过将某些信息写入数据库来加快速度的方法,当我重新运行软件时可以访问这些数据。出于这个原因,我需要能够为这些文件的任意子集生成唯一的文件名。

我尝试根据子集中的文件总大小和文件修改日期甚至它们的组合生成文件名。问题是许多文件具有相同的大小和相同的修改日期,这使我当前的标识符字符串不明确。重要的是,对于相同的文件列表,标识符始终相同,以便我始终可以访问相同文件的正确文件。非常感谢任何想法!

这是我目前使用的,不起作用......

import os
import glob
import datetime

file_paths = glob.glob("path/to/files/*.foo")

def modification_date(file_path):
    return datetime.datetime.fromtimestamp(os.path.getmtime(filename=file_path))

uid = [modification_date(f) for f in file_paths]
uid = [d.year + d.day + d.day + d.hour + d.minute + d.second for d in uid]
uid = sum(uid) // len(uid) + sum([os.path.getsize(f) for f in file_paths])

2 个答案:

答案 0 :(得分:1)

这可能会非常糟糕,但只要列表中包含的文件没有变化,您就可以获得hashlib后的内容吗?

import hashlib, glob
file_paths = glob.glob("/home/rolf/StackOverflow/*.py")
hash_object = hashlib.sha256(str(file_paths))
file_name= hash_object.hexdigest()
file_name
'f69dd9583eabae55319e9a56dbfc737cc16ab58634d9042f4c530e9a85e7d77c'

file_paths = glob.glob("/home/rolf/Research/*.py")
hash_object = hashlib.sha256(str(file_paths))
file_name= hash_object.hexdigest()
file_name
'dc4beec8e859b190d966068a52674d135f22520514ac1020b3e11a4af090e579'

答案 1 :(得分:0)

如果所有文件的主列表永远不会更改,则可以将该列表的任何子集唯一编码为大约len(master_list)/8个字符的字符串。首先,创建一个位数组,其中索引i处的0表示“主列表的第i个元素不是该子集的一部分”,1表示“主列表的第i个元素是该子集的一部分”。然后将位数组转换为整数,然后可以将其打包成字符串。

import struct
import base64

#encodes a positive integer of any size into a string.
def string_from_int(value):
    bytes = []
    while value > 0:
        bytes.append(value % 2**8)
        value >>= 8
    return struct.pack("i"*len(bytes), *bytes)

#decodes a string into a positive integer. Only works on strings whose length is divisible by 4.
def int_from_string(s):
    bytes = struct.unpack("i" * (len(s)/4), s)
    return sum(byte * (256**i) for i, byte in enumerate(bytes))

#encodes a subset of a list into a filename-safe string.
def encode(master_file_list, subset):
    bitmask = [int(filename in subset) for filename in master_file_list]
    int_value = sum(bit*2**(i) for i, bit in enumerate(bitmask))
    string_value = string_from_int(int_value)
    #the string may contain slashes or other characters illegal in filenames, so we b64 endoce it, at the expense of increasing the length by %20 or so
    return base64.urlsafe_b64encode(string_value)

#the reverse of `encode`.
def decode(master_file_list, filename):
    string_value = base64.urlsafe_b64decode(filename)
    int_value = int_from_string(string_value)
    subset = [value for i,value in enumerate(master_file_list) if (2**i) & int_value]
    return subset

master_file_list = ['caddy.jpg', 'fjeld.dat', 'gyve.ini', 'karts.png', 'laves.txt', 'nimbi.jpg', 'ocas.ini', 'sipes.dat', 'wacky.png', 'waff.png']
subset = ["fjeld.dat", "laves.txt", "ocas.ini"]
filename = encode(master_file_list, subset)
print "Subset is:", subset
print "Filename is:", filename
print "Filename decodes back to:", decode(master_file_list, filename)

结果:

Subset is: ['fjeld.dat', 'laves.txt', 'ocas.ini']
Filename is: UgAAAA==
Filename decodes back to: ['fjeld.dat', 'laves.txt', 'ocas.ini']