web-dev-qa-db-ja.com

ディレクトリを比較するがファイルの内容は比較しない

Diff -rを使用してこのタスクを実行できますが、diffがファイルの内容をチェックするため、非常に時間がかかります。

2つのファイルのサイズ、最終変更時などが同じであると判断するものが必要です。ただし、ファイルを少しずつチェックしないでください(たとえば、ビデオに時間がかかりすぎる)。

他に方法はありますか?

28
eez0

デフォルトでは、rsyncはファイルのメタデータのみを比較します。これは、タイムスタンプ、サイズ、および属性を意味します。とりわけ。ファイルのコンテンツではありません。

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

説明:

  • -n実際にコピーまたは削除しないでください<-THIS IS重要!! 1
  • -aタイムスタンプや属性のようなファイルのすべてのメタデータを比較します
  • -iファイルごとに1行の情報を出力します
  • --deleteソースにないファイルもレポートします

注:ディレクトリ名にスラッシュを追加することが重要です。これはrsyncのものです。

同一のファイルについて出力された行も確認したい場合は、-i 2回

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

出力例:

*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はメタデータのみを比較することに注意してください。つまり、ファイルの内容は変更されたがメタデータは同じままの場合、rsyncはそのファイルが同じであることを報告します。これはありそうもないシナリオです。したがって、メタデータが同じでデータが同じであると信頼するか、ファイルのデータを少しずつ比較する必要があります。

おまけ:進捗情報については、こちらを参照してください: rsyncの終了までの時間または作業の見積もり?

29
lesmana

使用 -q--brief)オプションとdiff -rdiff -qr)。 GNU infodiffページから:

1.6異なるファイルの要約

ファイルが異なるかどうかを確認するだけで、違いが気にならない場合は、サマリー出力形式を使用できます。この形式では、ファイル間の違いを示す代わりに、diff' simply reports whether files differ. The-- brief '( `-q')オプションは、この出力フォーマットを選択します。

この形式は、2つのディレクトリの内容を比較するときに特に役立ちます。また、 `diff 'は違いがあることがわかるとすぐにファイルの分析を停止できるため、通常の行ごとの比較を行うよりもはるかに高速です。

これは行ごとではなく、ファイル全体を比較するため、プロセッサー(探しているもの)が大幅に高速化されます。

3
laebshade

次に、ファイル名、mtimes、ファイルサイズがすべて同じであることを確認する簡単なpythonスクリプトを示します。

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])))
3
Chris Down

2つのファイルシステムブランチからのファイルが異なるかどうかを知る必要があるだけの場合(ファイル内を調べない)、次のようなことができます。

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

1
Chaky

Chris Downのスクリプトに基づいて、このスクリプトはもう少し「視覚的」です。 2つの引数で呼び出すfolder1およびfolder2、それは最初のフォルダーをウォークし、各ファイルについて2番目のフォルダー内の対応するファイルを検索します。見つかった場合、相対パスは緑色で印刷され、変更された時間またはサイズが異なる場合は黄色で印刷され、見つからない場合は赤色で印刷されます。

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

これはnotであることに注意してください。2つのフォルダが同じかどうかを判断するには十分です。確認するには、両方の方法で実行する必要があります。実際には、フォルダーが同じかどうかだけを知りたい場合、Chrisのスクリプトの方が適しています。 フォルダ間で不足しているものや異なるものを知りたい場合は、私のスクリプトが教えてくれます。

注:termcolorをインストールする必要があります、pip install termcolor

0
Jonathan H

ファイルの構造といくつかの基本的な情報のみを比較したい場合は、次のようなことを試すことができます。

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

私はそれをテストしなかったので、どんな編集も大歓迎です:)

0
Volodymyr