python डुप्लिकेट फाइल्स को हौशेल के जरिए खोजना?




file duplicates (3)

पहली चीज जिसे आप करना चाहते हैं वह h_md5 को आपकी सूची के अनुसार लूप में सहेज लेती है। कुछ इस तरह:

h_md5=[]

आपके निर्देशिका के माध्यम से लूप से पहले तथा

h_md5.append(getFileHashMD5(fullname))

अपने लूप के अंदर अब आपके पास अपनी आउटपुट फ़ाइल के साथ तुलना करने के लिए हैश की एक सूची है, जो कि आपके लूप में किए गए अंतिम फ़ाइल के बजाय

इसके अलावा, जाहिर है, आपके वर्तमान कोड के साथ आप प्रत्येक फाइल के लिए एक मैच हर बार ढूँढ़ने जा रहे हैं क्योंकि आपको अपनी सूची में उस विशेष फाइल के लिए हैश मिलेगा। इसलिए यदि आप डुप्लिकेट देखना चाहते हैं तो आपको उन उदाहरणों को देखना होगा जहां दो अलग-अलग मैचों पाए जाते हैं।

संपादित करें: @सेंडरले के ऊपर का उत्तर ऐसा करने का एक बेहतर तरीका है यदि आप अपना कोड बदलना चाहते हैं

मुझे पता है कि इस सवाल से पहले पूछा गया है, और मैंने कुछ जवाब देख लिए हैं, लेकिन यह प्रश्न मेरे कोड और इस कार्य को पूरा करने का सर्वोत्तम तरीका है।

मैं एक निर्देशिका को स्कैन करना चाहता हूं और देखें कि उस निर्देशिका में कोई भी डुप्लिकेट (एमडी 5 हैश चेक करके) निम्नलिखित मेरा कोड है:

import sys
import os
import hashlib

fileSliceLimitation = 5000000 #bytes

# if the file is big, slice trick to avoid to load the whole file into RAM
def getFileHashMD5(filename):
     retval = 0;
     filesize = os.path.getsize(filename)

     if filesize > fileSliceLimitation:
        with open(filename, 'rb') as fh:
          m = hashlib.md5()
          while True:
            data = fh.read(8192)
            if not data:
                break
            m.update(data)
          retval = m.hexdigest()

     else:
        retval = hashlib.md5(open(filename, 'rb').read()).hexdigest()

     return retval

searchdirpath = raw_input("Type directory you wish to search: ")
print ""
print ""    
text_file = open('outPut.txt', 'w')

for dirname, dirnames, filenames in os.walk(searchdirpath):
    # print path to all filenames.
    for filename in filenames:
        fullname = os.path.join(dirname, filename)
        h_md5 = getFileHashMD5 (fullname)
        print h_md5 + " " + fullname
        text_file.write("\n" + h_md5 + " " + fullname)   

# close txt file
text_file.close()


print "\n\n\nReading outPut:"
text_file = open('outPut.txt', 'r')

myListOfHashes = text_file.read()

if h_md5 in myListOfHashes:
    print 'Match: ' + " " + fullname

यह मुझे निम्न आउटपुट देता है:

Please type in directory you wish to search using above syntax: /Users/bubble/Desktop/aF

033808bb457f622b05096c2f7699857v /Users/bubble/Desktop/aF/.DS_Store
409d8c1727960fddb7c8b915a76ebd35 /Users/bubble/Desktop/aF/script copy.py
409d8c1727960fddb7c8b915a76ebd25 /Users/bubble/Desktop/aF/script.py
e9289295caefef66eaf3a4dffc4fe11c /Users/bubble/Desktop/aF/simpsons.mov

Reading outPut:
Match:  /Users/bubble/Desktop/aF/simpsons.mov

मेरा विचार था:

1) स्कैन डायरेक्टरी 2) एमडी 5 हैश + फाइलनाम को पाठ फ़ाइल में लिखें 3) ओपन टेक्स्ट फाइल को केवल पढ़ने के लिए लिखें 4) स्कैन डायरेक्टरी को फिर से और पाठ फ़ाइल से जांचें ...

मुझे लगता है कि यह करने का एक अच्छा तरीका नहीं है और यह काम नहीं करता है। 'मैच' बस उस अंतिम फ़ाइल को प्रिंट करता है जिसे संसाधित किया गया था।

मैं वास्तव में डुप्लिकेट को खोजने के लिए इस स्क्रिप्ट को कैसे प्राप्त करूं? क्या कोई मुझे इस कार्य को पूरा करने का एक बेहतर / आसान तरीका बता सकता है?

किसी भी सहायता के लिए आपका बहुत - बहुत धन्यवाद। क्षमा करें यह एक लंबा पोस्ट है


डुप्लिकेट की पहचान करने के लिए स्पष्ट उपकरण एक हैश तालिका है जब तक आप बहुत बड़ी फाइलों के साथ काम नहीं कर रहे हों, आप ऐसा कुछ कर सकते हैं:

from collections import defaultdict

file_dict = defaultdict(list)
for filename in files:
    file_dict[get_file_hash(filename)].append(filename)

इस प्रक्रिया के अंत में, file_dict में प्रत्येक अद्वितीय हैश के लिए एक सूची होगी; जब दो फ़ाइलों में एक ही हैश है, तो वे दोनों हथेली के लिए सूची में दिखाई देंगे। फिर डायन्ट को 1 से ज़्यादा मूल्य सूची की तलाश में फ़िल्टर करें, और फ़ाइलों की तुलना करके यह सुनिश्चित करें कि वे एक समान हैं - ऐसा कुछ:

for duplicates in file_dict.values():   # file_dict.itervalues() in Python 2
    if len(duplicates) > 1:
        # double-check reported duplicates and generate output

या यह:

duplicates = [files for files in file_dict.values() if len(files) > 1]

get_file_hash का उपयोग कर सकता है; या यह फ़ाइल के पहले और अंतिम बाइट्स को केवल रामचंद्र अपट्स के रूप में उपरोक्त टिप्पणियों में सुझाई गई हो सकती है; या यह केवल फ़ाइल आकारों का उपयोग कर सकता है जैसा कि ऊपर टिप्पणी में सुझाव दिया गया है। हालांकि, बाद की दो रणनीतियों में से प्रत्येक को झूठी सकारात्मक बनाने की संभावना है। आप गलत सकारात्मक दर को कम करने के लिए उन्हें जोड़ सकते हैं।

यदि आप बहुत बड़ी फाइलों के साथ काम कर रहे हैं, तो आप एक ब्लू फ़िल्टर जैसी अधिक परिष्कृत डेटा संरचना का उपयोग कर सकते हैं।


@सेंडरले का एक बहुत अच्छा जवाब है, लेकिन जब से उसने कहा कि मेरा समाधान झूठी सकारात्मक पैदा करेगा, मुझे लगा कि गड़बड़ी रखी गई थी और मैं कुछ कोड को बेहतर दिखाऊंगा। मैंने आपके एमडी 5 फ़ंक्शन को थक दिया (यह हमेशा 'फाइलस्लिस लिमिनेशन' मामले का उपयोग करना चाहिए और इसके इनपुट बफ़र के साथ कम चुभने वाला होना चाहिए), फिर एमडी 5s करने से पहले आकार से पहले छिद्र किया जाना चाहिए।

import sys
import os
import hashlib
from collections import defaultdict

searchdirpath = sys.argv[1]

size_map = defaultdict(list)

def getFileHashMD5(filename):
    m = hashlib.md5()
    with open(filename, 'rb', 1024*1024) as fh:
          while True:
            data = fh.read(1024*1024)
            if not data:
                break
            m.update(data)
    return m.hexdigest()

# group files by size
for dirname, dirnames, filenames in os.walk(searchdirpath):
    for filename in filenames:
        fullname = os.path.join(dirname, filename)
        size_map[os.stat(fullname).st_size].append(fullname)

# scan files of same size
for fullnames in size_map.itervalues():
    if len(fullnames) > 0:
        hash_map = defaultdict(list)
        for fullname in fullnames:
            hash_map[getFileHashMD5(fullname)].append(fullname)
        for fullnames in hash_map.itervalues():
            if len(fullnames) > 1:
                print "duplicates:"
                for fullname in fullnames:
                    print "   ", fullname

(संपादित)

इस कार्यान्वयन के बारे में कई सवाल थे कि मैं यहां उत्तर देने का प्रयास करूंगा:

1) क्यों (1024 * 1024) आकार नहीं '5000000'

आपका मूल कोड 8192 (8 कि.बा.) वेतन वृद्धि में पढ़ा है, जो आधुनिक प्रणालियों के लिए बहुत छोटा है। आप एक बार में अधिक हथियाने के द्वारा बेहतर प्रदर्शन प्राप्त कर सकते हैं 1024 * 1024 1048576 (1 MiB) बाइट्स हैं और यह उचित संख्या में अनुमान लगाया गया था। इसके लिए मैंने ऐसा क्यों लिखा था अजीब तरह से, 1000 (दशमलव किलोबाइट) लोगों द्वारा प्यार किया जाता है लेकिन 1024 (बाइनरी किबाइबेट) को कंप्यूटर और फाइल सिस्टम से प्यार है मैं some_number*1024 लिखने की आदत में some_number*1024 इसलिए यह देखने के लिए आसान है कि मैं 1 किबा की वेतन वृद्धि का some_number*1024 दे रहा हूं। 5000000 एक उचित संख्या भी है, लेकिन आपको 5 * 1024 * 1024 (जो कि 5 MiB है) पर विचार करना चाहिए ताकि आप कुछ ऐसी फ़ाइल प्राप्त कर सकें जो फ़ाइल सिस्टम के लिए अच्छी तरह से जुड़ा हो।

2) यह बिल्कुल ठीक क्या करता है: size_map = defaultdict (सूची)

यह एक 'डिफॉल्ट डिक्ट' बनाता है जो एक नियमित सिद्धांत वस्तु के लिए कार्यक्षमता जोड़ता है एक नियमित शब्दकोश एक keyError अपवाद उठाता है जब यह गैर-मौजूद कुंजी द्वारा अनुक्रमित किया जाता है defaultdict एक डिफ़ॉल्ट मान बनाता है और उस कुंजी / मान जोड़ी को dict में जोड़ता है। हमारे मामले में, size_map[some_size] कहते हैं, "मुझे some_size की फाइलों की सूची दें और यदि आपके पास एक नहीं है तो एक नई खाली सूची बनाएं"।

size_map[os.stat(fullname).st_size].append(fullname) । यह नीचे टूट जाता है:

stat = os.stat(fullname)
size = stat.st_size
filelist = size_map[size]    # this is the same as:
                             #    if size not in size_map:
                             #        size_map[size] = list()
                             #    filelist = size_map[size]
filelist.append(fullname)

3) sys.argv [1] मैं sys.argv अनुमान लगा रहा हूँ [1] बस अजगर py.py 'filepath' तर्क काम करता है (जहां फ़ाइलपथ argv [1] है?

हां, जब आप अजगर स्क्रिप्ट कॉल करते हैं, तो sys.argv [0] स्क्रिप्ट का नाम है और sys.argv [1:] (arg 1 और निम्न) कमांड लाइन पर दिए गए कोई अतिरिक्त तर्क हैं। मैंने sys.argv [1] को स्क्रिप्ट का परीक्षण करने का एक त्वरित तरीका के रूप में उपयोग किया जब मैंने इसे लिखा था और आपको अपनी ज़रूरतों को पूरा करने के लिए इसे बदलना चाहिए।





hashlib