1

2 つのディレクトリを再帰的に通過し、filename:sha256hash を folder1 と folder2 の 2 つの辞書に入れるプログラムがあります。

私がやりたいのは、ハッシュの比較であり、ハッシュが一致してもキーが異なる場合は、キーを「名前変更済み」と呼ばれる新しいリストに公開します。削除されたファイル、新しいファイル、およびキーが同じで値 (ハッシュ) が異なるファイル (変更されたファイル) を説明するためのロジックが用意されていますが、一生頭を悩ませることはできません。反対。

    # Put filename:hash into 2 dictionaries from the folders to compare

    for root, dirs, files in os.walk(folder_1):
        for file in files:
            files1[file] = get_hash(os.path.join(root,file))

    for root, dirs, files in os.walk(folder_2):
        for file in files:
            files2[file] = get_hash(os.path.join(root, file))

    # Set up the operations to do for the comparison 

    set_files2, set_files1 = set(files2.keys()), set(files1.keys())
    intersect = set_files2.intersection(set_files1)

    # Compare and add to list for display

    created.extend(set_files2 - intersect)
    deleted.extend(set_files1 - intersect)
    modified.extend(set(k for k in intersect if files1[k] != files2[k]))
    unchanged.extend(set(k for k in intersect if files1[k] == files2[k]))

これに関する問題は、1: 名前が変更されたファイルを考慮していない、2: 名前が変更されたファイルを作成済みに配置するため、ファイルの名前を変更したら、作成する必要がある = 作成 - 名前を変更して、実際の新しいファイルからそれらを除外する必要があります。

あらゆる/すべての助けをいただければ幸いです。ここまで来たのに、なぜか心がストライキ中。

4

3 に答える 3

3

files1と辞書を反転できfiles2ます:

name_from_hash1 =  {v:k for k, v in file1.items()}
name_from_hash2 =  {v:k for k, v in file2.items()}

(このSOの回答で見つけたフリッピングイディオム。)

それで、

renamed = []
for h in name_from_hash1:
    if h in name_from_hash2 and name_from_hash1[h] != name_from_hash2[h]:
        renamed.append(name_from_hash2[h])

renamed次に、現在の名前で名前が変更されたファイル名のリストです。最後の行を に変更すると、名前が変更name_from_hash2されたファイルの元の名前のリストを取得できます。name_from_hash

于 2013-06-20T17:51:21.600 に答える
2

ファイル名をキーとして、ハッシュを値として持つのではなく、ハッシュをキーとして、ファイル名を値として持つという簡単な解決策があります (結局のところ、値ではなくキーを一意にする必要があります)。それを考慮して、プログラムの残りの部分を調整するだけです。(おっと、Bitwise が既にコメントで言及しているようです。まあ。)

コードの残りの部分を変更したくない場合、Python 2.7 以降を使用している場合、名前を変更した一連のファイルを作成するための 1 つのライナーの方法を次に示します。

renamedfiles = {k for k, v in hashes1.items() if v in hashes2.values()}

Python 2.7 でわ​​ずかに効率を上げるには、代わりにiteritems()andを使用しitervalues()ます (Python 3 は、デフォルトでキー、アイテム、値のビューを反復子として表します)。

補遺: を行うこともできますがrenamedfiles = filter(lambda item:item in hashes2.values(), hashes1.items())、その結果、セットや辞書ではなく、修飾キー/値のペアに対する反復子が生成されます。filter()また、組み込みメソッドの 1 つですが、Python では一般的に内包表記が好まれると思います。

于 2013-06-20T17:53:33.583 に答える
0

これは、私がすぐに思いついた悪い多項式時間ソリューションですが、次のとおりです。

>>> d1 = {'a':1, 'b':2, 'c':3}    
>>> d2 = {'a':1, 'b':3, 'c':2}
>>> for key1 in d1:
...     for key2 in d2:
...             if d1[key1] == d2[key2] and key1 != key2:
...                     print key1, key2
... 
c b
b c

このコードd2は、値が のキーと同じであるキーを出力しd1ますが、2 つのキーが異なる場合のみです。変更されたキーをリストに入れるつもりだった方法に合わせて、これを調整してくださいmodified

于 2013-06-20T17:40:37.480 に答える