あるフォルダの特定の場所には表示されますが、別のフォルダには表示されないすべてのファイルを一覧表示するにはどうすればよいですか?

あるフォルダの特定の場所には表示されますが、別のフォルダには表示されないすべてのファイルを一覧表示するにはどうすればよいですか?

多くのサブフォルダーとファイルがあるフォルダー(「orig」と呼ばれる)と、異なるフォルダー構造にバックアップとして配置された同じファイルが多数ある別のフォルダー(「backup」と呼ばれます)があります。 「orig」にまだ存在していない「backup」のすべてのファイルをリストして、「orig」の正しいサブボリュームに入れて「backup」を削除できるようにしたいと思います。ファイル名とサイズを比較すれば十分です。

以前も同様の質問をされた方がいらっしゃいますが、お勧めする解決方法はですdiff -qr orig/ backup/。しかし、これを試みたとき、コマンドは1つのフォルダに表示され、別のフォルダには表示されませんでしたが、ファイルは表示されなかったため、再帰が機能しないことがわかりました。ここに例があります。まず、それぞれサブフォルダとファイルを含む2つのフォルダを作成します。各サブフォルダとファイルには異なるコンテンツがあります。

$ mkdir orig
$ mkdir backup
$ mkdir orig/1
$ mkdir backup/2
$ echo 'blah' > orig/1/test.txt
$ ls orig/1
test.txt
$ echo 'blah1' > backup/2/test1.txt

次に、-qrオプションを使用して比較します。

$ diff -qr orig/ backup/
Only in orig/: 1
Only in backup/: 2

次のいずれかのサブフォルダに移動すると、そのフォルダ内のファイルを見つけることができます。

$ diff -r orig/1 backup/
Only in backup/: 2
Only in orig/1: test.txt

実際に「-qr」があるかどうかにかかわらず、同じ動作が発生します。これはバグですか、それとも違いを誤解していますか?私はdiff(GNU diffutils)3.7を使用しています。

私の問題を解決する方法について他の提案がある場合は、非常に感謝します(例:単純なPythonスクリプト)。

ベストアンサー1

Pythonを使って問題を解決する方法を見つけました。

import filecmp
import os.path

def find_unique_files(path_orig, path_duplicates, ommit_in_orig=[]):
    """
    Crawls all subfolders of path_duplicates and
    returns list of files (incl. paths) that occur
    in path_duplicates but no-where in path_orig,
    except for folders listed in ommit_in_orig. 
    Do not forget to add trailing '/' at the end of paths.
    
    Arguments:
    path_orig -- string
    path_duplicates -- string
    ommit_in_orig -- list of strings
    
    Returns:
    list of strings indicating paths to files.
    
    Example:
        find_unique_files('/home/user/project/', 
                          '/home/user/project/backups/',
                          ommit_in_orig=['/home/user/project/backups/',
                                         '/home/user/project/temp/'])
    """
    unique_files = []
    for folder, subfolders, files in os.walk(path_duplicates):
        print(folder, end='\r')

        for file in files:
            unique = 1
            filepath = os.path.join(folder,file)
            for folder1, subFolders1, files1 in os.walk(path_orig):
                # Check if folder1 is a subfolder of ommit_in_orig
                ommit = [s for s in ommit_in_orig if s.lower() in folder.lower()]
                if len(ommit) == 0:
                    if file in files1:
                        filepath1 = os.path.join(folder1, file)
                        if filecmp.cmp(filepath,filepath1):
                            # File is identical
                            unique = 0
            if unique == 1:
                unique_files.append(filepath)
    return unique_files
path_orig = 'orig/'
path_duplicates = 'backup/'
find_unique_files(path_orig, path_duplicates)

おすすめ記事