So sánh thư mục nhưng không phải nội dung của tập tin


21

Với diff -r tôi có thể thực hiện tác vụ này, tuy nhiên phải mất rất nhiều thời gian vì diff kiểm tra nội dung của tệp.

Tôi muốn một cái gì đó xác định rằng hai tệp giống nhau về kích thước của chúng, được sửa đổi lần cuối, v.v. Nhưng không kiểm tra từng chút một tệp (ví dụ: một video mất nhiều thời gian)

Còn cách nào khác không?

Câu trả lời:


20

rsync, theo mặc định, chỉ so sánh siêu dữ liệu tệp.

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

giải trình:

  • -n không thực sự sao chép hoặc xóa <- ĐIỀU NÀY QUAN TRỌNG !! 1
  • -a so sánh tất cả siêu dữ liệu của tệp như dấu thời gian và thuộc tính
  • -i in một dòng thông tin trên mỗi tệp
  • --delete cũng báo cáo các tập tin không có trong nguồn

lưu ý: điều quan trọng là nối các tên thư mục bằng dấu gạch chéo. đây là một điều rsync.

nếu bạn cũng muốn xem các dòng được in cho các tệp giống hệt nhau thì hãy cung cấp -ihai lần

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

đầu ra ví dụ:

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

hãy nhớ rằng rsync chỉ so sánh siêu dữ liệu. điều đó có nghĩa là nếu nội dung tệp thay đổi nhưng siêu dữ liệu vẫn giữ nguyên thì rsync sẽ báo cáo rằng tệp đó giống nhau. đây là một kịch bản không thể xảy ra vì vậy hoặc tin tưởng rằng khi siêu dữ liệu giống nhau thì dữ liệu giống nhau hoặc bạn phải so sánh dữ liệu tệp từng bit một.

phần thưởng: để biết thông tin tiến bộ xem tại đây: Ước tính thời gian hoặc công việc còn lại để hoàn thành cho rsync?


1
Các dấu gạch chéo trong source/target/cả hai đều rất quan trọng! (Không có chúng, bạn sẽ so sánh tên thư mục nguồn và đích cùng với tên tệp con, vì vậy tất cả các tên tệp sẽ khác nhau.)
peschü

Tôi ước tôi đã đọc bình luận của bạn sớm hơn, điều này rất quan trọng! Tôi đã bỏ qua dấu gạch chéo trong nguồn và sau đó tôi tự hỏi tại sao các tệp trong mục tiêu không hiển thị dưới dạng *deleting, nhưng các tệp trong nguồn chỉ xuất hiện. Các dấu gạch chéo rất dễ vô tình quên và sau đó bạn nhận được một đầu ra hợp lý nhưng sai.
dùng643011

3

Sử dụng -q( --brief) tùy chọn với diff -r( diff -qr). Từ infotrang dành cho GNU diff:

1.6 Tóm tắt tập tin nào khác nhau

Khi bạn chỉ muốn tìm hiểu xem các tệp có khác nhau không và bạn không quan tâm sự khác biệt là gì, bạn có thể sử dụng định dạng đầu ra tóm tắt. Trong định dạng này, thay vì hiển thị sự khác biệt giữa các tệp, diff' simply reports whether files differ. Thetùy chọn --brief '(`-q') chọn định dạng đầu ra này.

Định dạng này đặc biệt hữu ích khi so sánh nội dung của hai thư mục. Nó cũng nhanh hơn nhiều so với thực hiện so sánh dòng bình thường bằng cách so sánh dòng, bởi vì 'diff' có thể ngừng phân tích các tệp ngay khi biết rằng có bất kỳ sự khác biệt nào.

Điều này sẽ không so sánh từng dòng, mà là toàn bộ tệp, giúp tăng tốc đáng kể bộ xử lý (những gì bạn đang tìm kiếm).


1
Vấn đề của - q là nó so sánh bình thường và khi tìm thấy sự khác biệt dừng lại (nếu là chế độ bình thường, nó sẽ tiếp tục so sánh), vì vậy nếu các tệp lớn giống nhau thì nó sẽ tồn tại rất nhiều.
eez0

2

Đây là một kịch bản python nhanh sẽ kiểm tra xem tên tệp, mtimes và kích thước tệp có giống nhau không:

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

Nếu bạn chỉ cần biết các tệp từ hai nhánh hệ thống tệp có khác nhau không (không cần nhìn vào các tệp), bạn có thể làm một cái gì đó như thế này:

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

Dựa trên kịch bản của Chris Down, kịch bản này có phần "trực quan" hơn một chút. Gọi nó với hai đối số folder1folder2, nó đi qua thư mục đầu tiên và cho mỗi tệp tìm kiếm một tệp tương ứng trong thư mục thứ hai. Nếu nó được tìm thấy, đường dẫn tương đối được in màu xanh lá cây, nếu chúng có thời gian hoặc kích thước được sửa đổi khác nhau, nó được in màu vàng và nếu không tìm thấy thì nó được in màu đỏ.

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

Lưu ý rằng điều này là không đủ để quyết định xem hai thư mục có giống nhau hay không, bạn sẽ cần chạy cả hai cách để đảm bảo. Trong thực tế nếu bạn chỉ muốn biết liệu các thư mục có giống nhau hay không , thì kịch bản của Chris sẽ tốt hơn. Nếu bạn muốn biết những gì còn thiếu hoặc khác nhau từ thư mục này sang thư mục khác , thì tập lệnh của tôi sẽ cho bạn biết.

LƯU Ý: bạn sẽ cần cài đặt termcolor , pip install termcolor.


0

Nếu bạn chỉ muốn so sánh một cấu trúc và một số thông tin cơ bản về các tệp, bạn có thể thử một cái gì đó như thế này:

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

Tôi đã không kiểm tra nó, vì vậy mọi chỉnh sửa đều được chào đón :)


2
Điều này sẽ không hoạt động vì tên thư mục cũng sẽ có trong kết quả.
Chris Xuống

Điều gì nếu chúng ta sẽ loại trừ cột đầu tiên với tên thư mục? như <(ls -laR | awk '{$ 1 = ""; print}')
Volodymyr

Không phải tất cả các dòng là tên thư mục, do đó sẽ không hoạt động đúng.
Chris Xuống

Tận dụng thực tế là mỗi người <()có một môi trường riêng. Đã chỉnh sửa.
một CVn
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.