我有一个包含许多子文件夹和文件的文件夹(我们称之为“orig”),另一个文件夹中许多相同的文件作为备份放置在不同的文件夹结构中(我们称之为“备份”)。我想列出“backup”中“orig”中尚不存在的所有文件,以便我可以将它们放入“orig”中正确的子卷中并删除“backup”。按文件名和大小进行比较就足够了。
之前也有人问过类似的问题,推荐的解决方案是diff -qr orig/ backup/
。但是,当我尝试此操作时,我发现递归不起作用,因为该命令列出了其中一个而不是另一个中出现的文件夹,但没有列出文件。这是一个例子。首先我创建两个文件夹,每个文件夹有一个子文件夹和一个文件,其中每个子文件夹和文件都有不同的内容:
$ 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?我正在使用 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)