Dosyaların dizinlerini karşılaştırın ancak içeriğini karşılaştırın


21

Diff -r ile bu görevi yapabilirim, ancak diff dosya içeriğini kontrol ettiği için çok uzun sürer.

Ben iki dosya boyutu, son değiştirilmiş, vb açısından aynı olduğunu belirleyen bir şey istiyorum. Ama dosya kontrol bit bit yok (örneğin bir video sooo uzun sürer)

Başka yolu var mı?

Yanıtlar:


20

rsync, varsayılan olarak, yalnızca dosya meta verilerini karşılaştırır.

rsync -n -a -i --delete source/ target/

açıklama:

  • -n aslında kopyalamayın veya silmeyin <- BU ÖNEMLİDİR! 1
  • -a zaman damgası ve öznitelikler gibi dosyanın tüm meta verilerini karşılaştır
  • -i dosya başına bir satır bilgi yazdır
  • --delete ayrıca kaynakta olmayan dosyaları da rapor et

not: Dizin adlarını eğik çizgi ile eklemek önemlidir. bu rsync bir şey.

aynı dosyalar için yazdırılan satırları da görmek istiyorsanız, -iiki kez sağlayın

rsync -n -a -ii --delete source/ target/

örnek çıktı:

*deleting   removedfile   (file in target but not in source)
.d..t...... ./            (directory with different timestamp)
>f.st...... modifiedfile  (file with different size and timestamp)
>f+++++++++ newfile       (file in source but not in target)
.f          samefile      (file that has same metadata. only with -ii)

rsync'in yalnızca meta verileri karşılaştırdığını unutmayın. yani dosya içeriği değiştiyse ancak meta veriler aynı kaldıysa, rsync dosyanın aynı olduğunu bildirecektir. bu beklenmedik bir senaryodur. bu nedenle ya meta veriler aynı olduğunda verilerin aynı olduğuna ya da dosya verilerini biraz parça karşılaştırmanız gerektiğine güvenin.

bonus: ilerleme bilgileri için buraya bakın: rsync için bitirmek üzere kalan süreyi mi yoksa kalan işi mi tahmin ediyorsunuz?


1
Eğik çizgiler source/ve target/her ikisi de çok önemlidir! (Bunlar olmadan, kaynak ve hedef dizin adlarını alt dosya adlarıyla karşılaştırırsınız, böylece tüm dosya adları farklı olur.)
peschü

Keşke yorumunu daha önce okumuş olsaydım, bu çok önemli! Eğik çizgiyi yalnızca kaynakta atladım ve sonra hedef dosyaların neden görünmediğini merak ediyordum *deleting, ancak kaynaktaki dosyalar sadece ortaya çıktı. Eğik çizgileri yanlışlıkla unutmak kolaydır ve daha sonra makul ama yanlış bir çıktı elde edersiniz.
user643011

3

Kullanın -q( --briefbirlikte) seçeneğini diff -r( diff -qr). infoGNU için sayfadan diff:

1.6 Hangi Dosyaların Farklı Olduğunu Özetleme

Yalnızca dosyaların farklı olup olmadığını öğrenmek istediğinizde ve farkların ne olduğunu umursamadığınızda, özet çıktı biçimini kullanabilirsiniz. Bu formatta, dosyalar arasındaki farkları göstermek yerine, diff' simply reports whether files differ. The--brief '(`-q') seçeneği bu çıktı formatını seçer.

Bu biçim, özellikle iki dizinin içeriğini karşılaştırırken kullanışlıdır. Aynı zamanda normal satır satır karşılaştırmalar yapmaktan çok daha hızlıdır, çünkü `diff 'herhangi bir fark olduğunu anladığında dosyaları analiz etmeyi durdurabilir.

Bu, satır satır değil, dosyayı bir bütün olarak karşılaştırır, bu da işlemciyi büyük ölçüde hızlandırır (aradığınız şey).


1
- q problemi normal karşılaştırmasıdır ve bir fark durduğunda (normal mod olsaydı karşılaştırmaya devam eder), bu yüzden büyük dosyalar aynıysa çok sürecektir.
eez0

2

Dosya adlarının, mtimes'lerin ve dosya boyutlarının aynı olup olmadığını kontrol edecek hızlı bir python betiği:

import os
import sys

def getStats(path):
    for pathname, dirnames, filenames in os.walk(path):
        for filename in ( os.path.join(pathname, x) for x in filenames ):
            stat = os.stat(filename)
            yield filename[len(path):], stat.st_mtime, stat.st_size

sys.exit(tuple(getStats(sys.argv[1])) != tuple(getStats(sys.argv[2])))

1

Yalnızca iki dosya sistemi dalındaki dosyaların farklı olup olmadığını bilmeniz gerekiyorsa (dosyaların içine bakmadan) şöyle bir şey yapabilirsiniz:

find /opt/branch1 -type f | sort | xargs -i md5sum {} >/tmp/branch1;
find /opt/branch2 -type f | sort | xargs -i md5sum {} >/tmp/branch2;
diff /tmp/branch1 /tmp/branch2;

HTH


0

Chris Down'un senaryosuna dayanarak, bu senaryo biraz daha "görsel" dir. İki argüman ile çağrılması folder1ve folder2, ilk klasörü yürür ve her dosya için ikinci klasörde karşılık gelen bir dosyayı arar. Bulunursa, göreli yol yeşil renkte yazdırılır, farklı değiştirilmiş zaman veya boyuta sahiplerse, sarı renkte yazdırılır ve bulunamazsa kırmızı olarak yazdırılır.

#!/usr/bin/env python

import os
import sys
from termcolor import colored

def compare_filestats(file1,file2):
    """
    Compares modified time and size between two files.
    Return:
        -1 if file1 or file2 does not exist
         0 if they exist and compare equal
         1 if they have different modified time, but same size
         2 if they have different size, but same modified time
         3 if they have different size, and different modified time
    """

    if not os.path.exists(file1) or not os.path.exists(file2):
        return -1

    stat1 = os.stat(file1)
    stat2 = os.stat(file2)

    return (stat1.st_mtime != stat2.st_mtime) \
        + 2*(stat1.st_size != stat2.st_size)

def compare_folders(folder1,folder2):
    """
    folder1: serves as reference and will be walked through
    folder2: serves as target and will be querried for each file in folder1

    Prints colored status for each file in folder1:
        missing: file was not found in folder2 
        mtime  : modified time is different
        size   : filesize is different
        ok     : found with same filestats
    """
    for dirpath, dirnames, filenames in os.walk(folder1):
        for file1 in ( os.path.join(dirpath, x) for x in filenames ):
            relpath = file1[len(folder1):]
            file2 = os.path.join( folder2, relpath )
            comp = compare_filestats(file1,file2)

            if comp < 0:
                status = colored('[missing]','red')
            elif comp == 1:
                status = colored('[mtime  ]','yellow')
            elif comp >= 2:
                status = colored('[size   ]','yellow')
            else:
                status = colored('[ok     ]','green')

            print status, relpath

if __name__ == '__main__':
    compare_folders(sys.argv[1],sys.argv[2])

Bu olduğunu unutmayın değil , iki klasörün aynı olup olmadığına karar için yeterli, bunu emin olmak için her iki yönde çalıştırmak gerekir. Pratikte , klasörlerin aynı olup olmadığını bilmek istiyorsanız , Chris'in senaryosu daha iyidir. Bir klasörden diğerine neyin eksik veya farklı olduğunu bilmek istiyorsanız , komut dosyam size söyleyecektir.

NOT: yüklü termcolor gerekir pip install termcolor.


0

Yalnızca bir yapıyı ve dosyalar hakkında bazı temel bilgileri karşılaştırmak isterseniz, şöyle bir şey deneyebilirsiniz:

diff <(cd $DIR1 && ls -laR) <(cd $DIR2 && ls -laR)

Test etmedim, bu yüzden herhangi bir düzenleme bekliyoruz :)


2
Dizin adlarının kendisi de sonuçlarda olacağından bu çalışmaz.
Chris Down

ilk sütunu dizin adlarıyla hariç tutarsak ne olur? like <(ls -laR | awk '{$ 1 = ""; print}')
Volodymyr

Tüm satırlar dizin adı değildir, bu nedenle düzgün çalışmaz.
Chris Down

Her <()birinin kendi ortamına sahip olmasından yararlanın . Düzenlenen.
CVn
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.