İkili / Karma, OSX'deki klasör yapısını yoksayırken farklı konumlardaki dosyaları karşılaştırarak


2

Dosyaları iki farklı konum kümesinde , tercihen sadece dosya adından biraz daha kapsamlı bir şekilde karşılaştırmak için bir yola ihtiyacım var .

Geçenlerde ofis için yeni bir NAS aldık ve çeşitli USB sabit sürücülerden veri aktarıyoruz. Tüm dosyaların başarıyla taşındığını doğrulamak istiyorum.

Birçok dosya karşılaştırma programına baktım ancak çoğu dosyaların bulunduğu dizin yapısına duyarlı. İdeal olarak, yalnızca USB1, USB2 ve USB3 sürücülerindeki tüm dosyaları karma (MD5 veya benzeri) ve ardından NAS-VOLUME1 ve NAS-VOLUME2 üzerindeki tüm dosyaları karma olarak almak ve hangi dosyaların eksik olduğunu görmek için listeleri karşılaştırmak istiyorum. yan.

Bunun bir komut dosyasıyla veya komut satırından yapılabileceğinden şüpheleniyorum, ancak OSX'teki komut satırında çalışmak konusunda fazla aşina değilim (normalde bir windows türü adam).

Herhangi bir işaretçi çok takdir


Bu python ile kolaydır. OSX'de hangi seçeneklerin bulunduğundan emin değilim.
Eric Roper,

Aslında c # 'da bir şey patladım ama RAM'in tükenmeye devam ediyorum. Bunu yapacak herhangi bir Python betiği örneği var mı?
mynameisdev

Yanıtlar:


1

fdupesMac'te varsa, bunu yapabilir. Tüm disklerinizi takar ve fdupes'in tüm dizinleri geçmesine izin verirsiniz. Bu konuda da çok etkili olurdu (sadece aynı boyuttaki dosyaları karşılaştırmak, çünkü benzersiz bir dosya boyutuna sahip dosyalar çoğaltılamaz, vs.). İstenmeyen kopyaları silmek için sık sık fdupes kullanıldığından dikkatli olun, bu nedenle birçok örnekte bunlarda silme seçenekleri olabilir.


Bu Mac'te fdupes için mantıklı bir yükleme yolu bulamıyorum. Bir yerde bir dizüstü bilgisayarda Ubuntu'yu buldum ama bu arada, başka bir fikir, bir GUI ile bir şeyler harika olurdu ...
mynameisdev

0

Bu sürüm, dosya adları ve alt dizin yapıları her iki konumda da aynıysa çalışır. Bu sürümün avantajı, hafıza dostu olması. Bu basit hatalara karşı hafifçe test edilmiştir, ancak hesaba katılması daha muhtemeldir. Ayrıca, bir bash yaklaşımı, python'un çok fazla yüke sahip olması nedeniyle çok daha etkili olacaktır. Veri boyutuna bağlı olarak bu uzun zaman alabilir.

import os
import hashlib

def hash(file):
  f = open(file,'rb')
  h = hashlib.md5()
  checkEOF = b' '
  while checkEOF != b'':
    checkEOF = f.read(1024)
    h.update(checkEOF)
  f.close()
  return h.hexdigest()


def Hashwalk(d1, d2):
  errlist = []
  log = []
  walkobject1 = os.walk(d1)
  walkobject2 = os.walk(d2)
  try:
    for walks in zip(walkobject1,walkobject2):
      dir1 = walks[0][0]
      dir2 = walks[1][0]
      files1 = walks[0][2]
      files2 = walks[1][2]
      for files in zip(files1,files2):
        try:
          pathfile1 = os.path.join(dir1,files[0])
          pathfile2 = os.path.join(dir2,files[1])
          digest1 = hash(pathfile1)
          digest2 = hash(pathfile2)
          if digest1 != digest2:
            log.append((pathfile1, digest1, pathfile2, digest2))
        except PermissionError as error:    
          errlist.append((pathfile1,error))
        except FileNotFoundError as error:
          errlist.append((pathfile1,error))        
  except KeyboardInterrupt:
    print('Program terminated, results may be incomplete')
  return (log,errlist)

def ToDisk(hw):
  diff = open('differenthashes.txt','w',encoding='utf-8')
  for pair in hw[0]:
    diff.write(pair[0]+','+pair[1]+'\n')
    diff.write(pair[2]+','+pair[3]+'\n')
  if hw[1]:  
    diff.write('\nerrors\n')
    for error in hw[1]:
      diff.write(error[0]+','+error[1]+'\n')
  else:
    diff.write('no errors detected')
  diff.close()

ToDisk(Hashwalk('test1','test2'))

0

Şu anda bu betiğin hesap verdiği tek hata PermissionError ve FileNotFoundError. Bazı karakterler kodlama dizeleriyle gösterildiğinden ve bu şekilde bir FileNotFoundError ile sonuçlandığından doğru şekilde işlenemiyor. Senaryo uzun sürüyor ve birikmiş sonuçları görmek istersen bir KeyboardInterrupt istisnası ekledim. Bu betiğin çalıştırıldığı dizin, differenthashes.txt adlı bir dosya içerecektir.

Çalıştırmak için sadece alt kısımdaki compare () çağrısında 'path1' ve 'path2' ifadelerini kullanın. Herhangi bir öneriniz varsa veya bu ihtiyacınızı uygun şekilde değerlendirmiyorsanız, bana bildirin.

import os
import hashlib
import time

def hash(file):
  f = open(file,'rb')
  h = hashlib.md5()
  checkEOF = b' '
  while checkEOF != b'':
    checkEOF = f.read(1024)
    h.update(checkEOF)
  f.close()
  return h.hexdigest()

def hashwalk(d = './'):
  errlist = []
  hashes = []
  cwd = os.getcwd()
  os.chdir(d)
  walkobject = os.walk('./')
  try:
    for directory in walkobject:
      dir = directory[0]
      files = directory[2]
      for file in files:
        try:
          pathfile = os.path.join(dir,file)
          digest = hash(pathfile)
          hashes.append((pathfile,digest))
        except PermissionError as error:    
          errlist.append((pathfile,error))
        except FileNotFoundError as error:
          errlist.append((pathfile,error))
  except KeyboardInterrupt:
    print('Program terminated, results may be incomplete')
  os.chdir(cwd)
  return [hashes,errlist]

def compare(path1,path2,logerrors = False):
  loc1 = hashwalk(path1)
  loc2 = hashwalk(path2)
  differenthash = set(loc1[0]).symmetric_difference(set(loc2[0]))
  log = open('differenthashes.txt','w',encoding='utf-8')
  log.write('path                                          hash                                 date modified\n')
  for f,h in sorted(differenthash):
    if (f,h) in loc1[0]:
      print(path1+'\\'+f[2:],h,time.ctime(os.stat(path1+'\\'+f[2:]).st_mtime))
      log.write(path1 + ' ' +f[2:] + ' ' + h + ' ' + time.ctime(os.stat(path1+'\\'+f[2:]).st_mtime)+'\n')
    else:
      print(path2+'\\'+f[2:],h,time.ctime(os.stat(path2+'\\'+f[2:]).st_mtime))
      log.write(path2 + ' ' +f[2:] + ' ' + h + ' ' + time.ctime(os.stat(path2+'\\'+f[2:]).st_mtime)+'\n')
  if logerrors:
    log.write('\n\n'+path1+' errors\n')
    for error in loc1[1]:
      log.write(str(error) + '\n')
    log.write('\n'+path2+' errors\n')
    for error in loc2[1]:
      log.write(str(error) +'\n')
  log.close()

compare('path1', 'path2' ,logerrors=True)

Bu size bir MemoryError verirse ve alt dizin yapısı her iki yerde de aynıysa, karşılaştırmaları doğrudan hashwalk () öğesine taşıyabilir ve listeler olmadan karşılaştırabilirsiniz. Önce bu sürümü deneyeceğim ve işe yararsa yazımı düzenleyeceğim.
Eric Roper
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.