如何比较两个文件夹并将差异复制到第三个文件夹?


23

您有三个文件夹:

  • 当前文件夹,其中包含您的当前文件
  • 文件夹old,其中包含相同文件的旧版本
  • 文件夹差异,这只是一个空文件夹

你如何比较当前和副本是不同的(或全新的)中的文件当前区别


我已经四处搜寻,似乎很容易解决,但在我的特定示例中却无法解决。大多数资源都建议使用rsync,因此我得到了以下命令:

rsync -ac --compare-dest=../old/ new/ difference/

但是,这样做是将所有文件从新文件复制到不同文件,甚至与文件相同。

万一它有帮助(也许命令很好并且故障在其他地方),这就是我测试的方式:

  1. 我做了三个文件夹。
  2. 我提出了一些文本文件,在不同的内容
  3. 我将文件从复制到
  4. 我在new中更改了某些文件的内容,并添加了一些其他文件。
  5. 我运行了上面的命令,并检查了结果差异

在过去的几天里,我一直在寻找解决方案,非常感谢您的帮助。它不一定必须使用rsync,但如果可能的话,我想知道我在做什么错。



@wingedsubmariner我不认为它是重复的,因为链接问题上的可接受答案是OP提出问题的命令。
伯恩哈德

@伯恩哈德啊,我不好。我想我误解了最初的问题。
wingedsubmariner 2013年

@wingedsubmariner不用担心,您说“可能”,我同意它看起来非常相似:)
Bernhard

Answers:


7

我不确定是否可以使用任何现有的linux命令(例如rsync或diff)来做到这一点。但就我而言,我必须使用Python编写自己的脚本,因为python具有用于文件比较的“ filecmp”模块。我已经将整个脚本和用法发布到了我的个人网站-http://linuxfreelancer.com/

它的用法很简单-依次指定新目录,旧目录和差异目录的绝对路径。

#!/usr/bin/env python

import os, sys
import filecmp
import re
from distutils import dir_util
import shutil
holderlist=[]

def compareme(dir1, dir2):
    dircomp=filecmp.dircmp(dir1,dir2)
    only_in_one=dircomp.left_only
    diff_in_one=dircomp.diff_files
    dirpath=os.path.abspath(dir1)
    [holderlist.append(os.path.abspath( os.path.join(dir1,x) )) for x in only_in_one]
    [holderlist.append(os.path.abspath( os.path.join(dir1,x) )) for x in diff_in_one]
    if len(dircomp.common_dirs) > 0:
        for item in dircomp.common_dirs:
            compareme(os.path.abspath(os.path.join(dir1,item)), os.path.abspath(os.path.join(dir2,item)))
        return holderlist

def main():
 if len(sys.argv) > 3:
   dir1=sys.argv[1]
   dir2=sys.argv[2]
   dir3=sys.argv[3]
 else:
   print "Usage: ", sys.argv[0], "currentdir olddir difference"
   sys.exit(1)

 if not dir3.endswith('/'): dir3=dir3+'/'

 source_files=compareme(dir1,dir2)
 dir1=os.path.abspath(dir1)
 dir3=os.path.abspath(dir3)
 destination_files=[]
 new_dirs_create=[]
 for item in source_files:
   destination_files.append(re.sub(dir1, dir3, item) )
 for item in destination_files:
  new_dirs_create.append(os.path.split(item)[0])
 for mydir in set(new_dirs_create):
   if not os.path.exists(mydir): os.makedirs(mydir)
#copy pair
 copy_pair=zip(source_files,destination_files)
 for item in copy_pair:
   if os.path.isfile(item[0]):
    shutil.copyfile(item[0], item[1])

if __name__ == '__main__':
 main()

21

我已经弄清楚问题所在:

我正在比较的文件具有不同的时间戳。我不应该使用-a参数,因为Rsync在复制文件时试图保留时间戳。对我有用的命令是:

rsync -rvcm --compare-dest=../old/ new/ difference/

我认为要使用-a(归档)选项进行测试,您应该首先用于rsync -a“复制”文件(或等效的cp),然后删除或修改。(我喜欢坚持使用rsync,因为我知道它是自洽的,无需考虑它可能在做什么。)我认为这应该与原始命令一起使用。-a选项包括-t(按时间戳比较),它是-c(按校验和比较)的替代方法。
Sage 2014年

2
我认为,该答案应该是被接受的答案,因为它要简单得多。此外,将只工作对我来说,当我提供的完整路径old/new/
Yamaneko,2015年

需要说明的是,比较目标必须是从实际目标内部看到的差异的相对路径
Ryan Williams,

1

这可能对某些读者有帮助:在Windows中,一个较旧的,几乎免费的软件程序-Third Dir-确实可以满足此处的要求。它不再通过开发人员RobertVašíček提供。但我敢肯定,可以通过一些在线存储库找到它。

这是开发者的描述,保留在他的网站上:

第三目录:一个异常的目录同步器-将不同的文件复制到第三目录。从固定磁盘上的巨大目录树中将新照片或编辑过的照片提取到临时文件夹,然后将其添加到存档CD(请注意-将原始文件与CD进行比较),这非常有用。版本1.4,大小为23kB。创建于2005-02-12。

历史记录:1.14版-比较上万个文件时,效率更高。


0

Thane与Yamaneko附加组件给出的rsync方式很好用,但保留了空目录。对我来说,最终的解决方案分两个步骤,首先用完整路径调用rsync,然后使用find命令删除所有空目录:

rsync -rvcm --compare-dest=/tmp/org/ /tmp/new/ /tmp/difference/
find /tmp/difference/ -d -type d -empty -exec rmdir {} \; -print

请注意,即使使用--links选项,rsync也不保留符号链接,而是复制目标数据。


请注意,-empty -exec rmdir {} \;您可以使用代替-empty -delete
mivk

-3

我使用双窗格XY资源管理器(商业),它可以完成很多技巧,这就是其中之一。Current在一个窗格中打开,在另一个窗格中打开。激活当前窗格。转到窗格 > 同步选择。它为您提供5种选择:

  1. 匹配项(两者均列出)
  2. 唯一身份(在活动窗格中)
  3. 较新(在活动窗格中)
  4. 唯一文件和较新文件(在活动窗格中)
  5. 选中(在其他窗格中选中的那些)

现在,您可以将结果选择从复制Current到所需位置。我用它来比较mailfolders旧安装和最新安装。文件夹结构非常复杂,但是(几乎)所有文件夹mbs-files都有一个唯一的编号。

因此,我mbs-files在旧根目录mailfolder(在一个窗格中)和最新根目录(在另一个窗格中)中进行了搜索,并对每个窗格中的搜索结果进行了比较(“ 同步选择唯一”,以查找在此期间丢失的邮件重新安装)!您也可以设置很多选项。


1
如果您在谈论非标准软件,则应包括一个链接。如果您的意思是XYplorer根本不会帮助OP。
Anthon 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.