19

在继续使用 SVN 之前,我曾经通过简单地保留一个/develop/目录并在那里编辑和测试文件,然后将它们移动到该/main/目录来管理我的项目。当我决定迁移到 SVN 时,我需要确保目录确实是同步的。

那么,编写 shell 脚本 [ bash ] 以递归比较两个不同目录中同名文件的好方法是什么?

注意:上面使用的目录名称仅用于示例。我不建议将您的代码存储在顶层:)。

4

6 回答 6

33

diff 命令有一个 -r 选项来递归比较目录:

diff -r /develop /main
于 2008-09-23T08:21:57.610 回答
8
diff -rqu /develop /main

它只会以这种方式为您提供更改的摘要:)

如果您只想查看新的/丢失的文件

diff -rqu /develop /main | grep "^Only

如果你想让它们裸露:

diff -rqu /develop /main | sed -rn "/^Only/s/^Only in (.+?): /\1/p"
于 2008-09-23T08:46:22.700 回答
5

我可用的差异允许递归差异:

diff -r main develop

但是使用 shell 脚本:

( cd main ; find . -type f -exec diff {} ../develop/{} ';' )
于 2008-09-23T08:26:17.490 回答
1

[我在某处读到回答你自己的问题是可以的,所以这里是:)]

我试过这个,效果很好

[/]$ cd /develop/
[/develop/]$ find | while read line; do diff -ruN "/main/$line" $line; done |less

您可以选择仅比较特定文件 [例如,仅 .php 文件],方法是将上述行编辑为

[/]$ cd /develop/
[/develop/]$ find -name "*.php" | while read line; do diff -ruN "/main/$line" $line; done |less

还有其他想法吗?

于 2008-09-23T08:22:06.673 回答
1

这是我的一个(有些混乱的)脚本示例,dircompare.sh,它将:

  • 在两个递归过程中,根据它们出现在(或两者)中的目录对数组中的文件和目录进行排序
  • 两个目录中出现的文件在两个数组中再次排序,取决于是否diff -q确定它们是否不同
  • 对于那些diff声称相等的文件,显示并比较时间戳

希望它可以有用 - 干杯!

EDIT2:(实际上,它适用于远程文件 - 问题是在本地和远程文件之间的差异操作期间未处理的 Ctrl-C 信号,这可能需要一段时间;脚本现在更新了一个陷阱来处理这个问题 - 但是,留下下面的先前编辑供参考):

编辑:...除了它似乎使我的服务器崩溃以获取远程 ssh 目录(我尝试使用 over ~/.gvfs)...所以这不再是bash了,但我想另一种方法是使用rsync,这是一个示例:

$ # get example revision 4527 as testdir1
$ svn co https://openbabel.svn.sf.net/svnroot/openbabel/openbabel/trunk/data@4527 testdir1

$ # get earlier example revision 2729 as testdir2
$ svn co https://openbabel.svn.sf.net/svnroot/openbabel/openbabel/trunk/data@2729 testdir2

$ # use rsync to generate a list 
$ rsync -ivr --times --cvs-exclude --dry-run testdir1/ testdir2/
sending incremental file list
.d..t...... ./
>f.st...... CMakeLists.txt
>f.st...... MACCS.txt
>f..t...... SMARTS_InteLigand.txt
...
>f.st...... atomtyp.txt
>f+++++++++ babel_povray3.inc
>f.st...... bin2hex.pl
>f.st...... bondtyp.h
>f..t...... bondtyp.txt
...

注意:

  • 要获得上述内容,您不能忘记/目录名称末尾的斜杠rsync
  • --dry-run- 仅模拟,不更新/传输文件
  • -r- 递归到目录
  • -v- 详细(但文件更改信息无关)
  • --cvs-exclude- 忽略.svn文件
  • -i- “--itemize-changes:输出所有更新的变更摘要”

以下是man rsync解释由-i(例如,>f.st......上面的字符串)显示的信息的简短摘录:

The  "%i"  escape  has a cryptic output that is 11 letters long.
The general format is like the string YXcstpoguax,  where  Y  is
replaced  by the type of update being done, X is replaced by the
file-type, and the other letters represent attributes  that  may
be output if they are being modified.

The update types that replace the Y are as follows:

o      A  < means that a file is being transferred to the remote
       host (sent).

o      A > means that a file is being transferred to  the  local
       host (received).

o      A  c  means that a local change/creation is occurring for
       the item (such as the creation  of  a  directory  or  the
       changing of a symlink, etc.).

...
The file-types that replace the X are: f for a file, a d  for  a
directory,  an  L for a symlink, a D for a device, and a S for a
special file (e.g. named sockets and fifos).

The other letters in the string above  are  the  actual  letters
that  will be output if the associated attribute for the item is
being updated or a "." for no change.  Three exceptions to  this
are:  (1)  a newly created item replaces each letter with a "+",
(2) an identical item replaces the dots with spaces, and (3)  an
....

确实有点神秘 - 但至少它显示了基本的目录比较ssh。干杯!

于 2011-07-18T23:55:50.940 回答
0

经典的(System V Unix)答案是dircmp dir1 dir2,它是一个 shell 脚本,它会列出在 dir1 但不是 dir2 或在 dir2 但不是 dir1 中找到的文件(输出的第一页,来自pr命令,所以用标题分页),然后将每个常见文件与分析进行比较(相同、不同、目录是最常见的结果)。

这似乎正在消失的过程中 - 如果您需要,我可以独立重新实现它。这不是火箭科学(cmp是你的朋友)。

于 2008-10-18T18:45:54.133 回答