Bandingkan direktori tetapi bukan isi file


21

Dengan diff -r saya bisa melakukan tugas ini, namun butuh waktu lama karena diff memeriksa konten file.

Saya ingin sesuatu yang menentukan bahwa dua file adalah sama tentang ukurannya, terakhir dimodifikasi, dll. Tapi tidak memeriksa sedikit demi sedikit file (misalnya video butuh waktu lama)

Apakah ada cara lain?

Jawaban:


20

rsync, secara default, hanya membandingkan metadata file.

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

penjelasan:

  • -n jangan menyalin atau menghapus <- INI PENTING !! 1
  • -a bandingkan semua metadata file seperti cap waktu dan atribut
  • -i cetak satu baris informasi per file
  • --delete juga melaporkan file yang tidak ada dalam sumber

Catatan: penting untuk menambahkan nama direktori dengan garis miring. ini adalah hal rsync.

jika Anda juga ingin melihat garis yang dicetak untuk file yang identik maka berikan -idua kali

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

contoh output:

*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)

ingat bahwa rsync hanya membandingkan metadata. itu berarti jika konten file berubah tetapi metadata tetap sama maka rsync akan melaporkan file itu sama. ini adalah skenario yang tidak mungkin. jadi percaya bahwa ketika metadata sama maka datanya sama, atau Anda harus membandingkan data file sedikit demi sedikit.

bonus: untuk informasi kemajuan lihat di sini: Perkirakan waktu atau pekerjaan tersisa untuk menyelesaikan rsync?


1
Garis miring source/dan target/keduanya sangat penting! (Tanpa mereka, Anda akan membandingkan nama direktori sumber dan target bersama dengan nama file anak, sehingga semua nama file akan berbeda.)
peschü

Saya harap saya telah membaca komentar Anda sebelumnya, ini sangat penting! Saya mengabaikan slash in source saja dan kemudian saya bertanya-tanya mengapa file dalam target tidak muncul sebagai *deleting, tetapi file, yang dalam sumber hanya muncul. Garis miring mudah untuk dilupakan secara tidak sengaja dan kemudian Anda mendapatkan hasil yang masuk akal tetapi salah.
user643011

3

Gunakan opsi -q( --brief) dengan diff -r( diff -qr). Dari infohalaman untuk GNU diff:

1.6 Meringkas File Yang Berbeda

Ketika Anda hanya ingin mengetahui apakah file berbeda, dan Anda tidak peduli apa perbedaannya, Anda dapat menggunakan format output ringkasan. Dalam format ini, alih-alih menunjukkan perbedaan antara file, diff' simply reports whether files differ. Theopsi --brief '(`-q') memilih format output ini.

Format ini sangat berguna ketika membandingkan isi dari dua direktori. Ini juga jauh lebih cepat daripada melakukan perbandingan baris per baris yang normal, karena `diff 'dapat berhenti menganalisis file segera setelah ia mengetahui bahwa ada perbedaan.

Ini tidak akan membandingkan baris per baris, melainkan file secara keseluruhan, yang sangat mempercepat prosesor (apa yang Anda cari).


1
Masalahnya - q adalah membandingkan normal dan ketika menemukan perbedaan berhenti (jika mode normal itu terus membandingkan), jadi jika file besar sama itu akan bertahan banyak.
eez0

2

Berikut ini adalah skrip python cepat yang akan memeriksa apakah nama file, mtimes, dan ukuran file semuanya sama:

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

Jika Anda hanya perlu tahu apakah file dari dua cabang sistem file berbeda (tanpa melihat ke dalam file) Anda dapat melakukan sesuatu seperti ini:

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

Berdasarkan skrip Chris Down, skrip ini sedikit lebih "visual". Menyebutnya dengan dua argumen folder1dan folder2, berjalan di folder pertama dan untuk setiap file mencari file yang sesuai di folder kedua. Jika ditemukan, jalur relatif dicetak dalam warna hijau, jika mereka memiliki waktu atau ukuran yang dimodifikasi berbeda, itu dicetak dalam warna kuning, dan jika tidak ditemukan maka dicetak dalam warna merah.

#!/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])

Perhatikan bahwa ini tidak cukup untuk memutuskan apakah kedua folder itu sama, Anda harus menjalankan keduanya untuk memastikan. Dalam praktiknya jika Anda hanya ingin tahu apakah foldernya sama , maka skrip Chris lebih baik. Jika Anda ingin tahu apa yang hilang atau berbeda dari satu folder ke folder lainnya , maka skrip saya akan memberi tahu Anda.

CATATAN: Anda perlu menginstal termcolor pip install termcolor,.


0

Jika Anda ingin membandingkan hanya struktur dan beberapa info dasar tentang file, Anda dapat mencoba sesuatu seperti ini:

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

Saya tidak mengujinya, jadi ada suntingan selamat datang :)


2
Ini tidak akan berfungsi karena nama direktori itu sendiri juga akan ada dalam hasil.
Chris Down

bagaimana jika kita akan mengecualikan kolom pertama dengan nama direktori? seperti <(ls -laR | awk '{$ 1 = ""; print}')
Volodymyr

Tidak semua baris adalah nama direktori, sehingga tidak akan berfungsi dengan baik.
Chris Down

Manfaatkan fakta bahwa masing-masing <()memiliki lingkungannya sendiri. Diedit.
CVn
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.