bash 如何使用shell脚本比较两个不同目录中具有相同名称的文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/119788/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to compare files with same names in two different directories using a shell script
提问by Animesh
Before moving on to use SVN, I used to manage my project by simply keeping a /develop/
directory and editing and testing files there, then moving them to the /main/
directory. When I decided to move to SVN, I needed to be sure that the directories were indeed in sync.
在继续使用 SVN 之前,我曾经通过简单地保留一个/develop/
目录并在那里编辑和测试文件,然后将它们移动到/main/
目录来管理我的项目。当我决定迁移到 SVN 时,我需要确保目录确实是同步的。
So, what is a good way to write a shell script [ bash ] to recursively compare files with the same name in two different directories?
那么,编写 shell 脚本 [bash] 来递归比较两个不同目录中的同名文件的好方法是什么?
Note: The directory names used above are for sample only. I do not recommend storing your code in the top level :).
注意:上面使用的目录名称仅用于示例。我不建议将您的代码存储在顶级:)。
回答by Greg Hewgill
The diff command has a -r option to recursively compare directories:
diff 命令有一个 -r 选项来递归比较目录:
diff -r /develop /main
回答by Kent Fredric
diff -rqu /develop /main
It will only give you a summary of changes that way :)
它只会以这种方式为您提供更改摘要:)
If you want to see only new/missingfiles
如果您只想查看新的/丢失的文件
diff -rqu /develop /main | grep "^Only
If you want to get them bare:
如果你想让它们裸露:
diff -rqu /develop /main | sed -rn "/^Only/s/^Only in (.+?): //p"
回答by paxdiablo
The diff I have available allows recursive differences:
我可用的差异允许递归差异:
diff -r main develop
But with a shell script:
但是使用shell脚本:
( cd main ; find . -type f -exec diff {} ../develop/{} ';' )
回答by Animesh
[I read somewhere that answering your own questions is OK, so here goes :) ]
[我在某处读到回答你自己的问题是可以的,所以这里是:)]
I tried this, and it worked pretty well
我试过这个,效果很好
[/]$ cd /develop/
[/develop/]$ find | while read line; do diff -ruN "/main/$line" $line; done |less
You can choose to compare only specific files [e.g., only the .php ones] by editing the above line as
您可以选择仅比较特定文件 [例如,仅 .php 文件] 通过将上述行编辑为
[/]$ cd /develop/
[/develop/]$ find -name "*.php" | while read line; do diff -ruN "/main/$line" $line; done |less
Any other ideas?
还有其他想法吗?
回答by sdaau
here is an example of a (somewhat messy) script of mine, dircompare.sh, which will:
这是我的(有点凌乱的)脚本示例dircompare.sh,它将:
- sort files and directories in arrays depending on which directory they occur in (or both), in two recursive passes
- The files that occur in both directories, are sorted again in two arrays, depending on if
diff -q
determines if they differ or not - for those files that
diff
claims are equal, show and compare timestamps
- 在两次递归传递中,根据它们出现在(或两者)中的目录对数组中的文件和目录进行排序
- 出现在两个目录中的文件,在两个数组中再次排序,这取决于是否
diff -q
确定它们是否不同 - 对于那些
diff
声称相等的文件,显示并比较时间戳
Hope it can be found useful - Cheers!
希望它可以被发现有用 - 干杯!
EDIT2: (Actually, it works fine with remote files - the problem was unhandled Ctrl-C signal during a diff operation between local and remote file, which can take a while; script now updated with a trap to handle that - however, leaving the previous edit below for reference):
EDIT2:(实际上,它适用于远程文件 - 问题是在本地和远程文件之间的差异操作期间未处理的 Ctrl-C 信号,这可能需要一段时间;脚本现在更新了一个陷阱来处理这个问题 - 但是,留下下面的先前编辑供参考):
EDIT: ... except it seems to crash my server for a remote ssh directory (which I tried using over ~/.gvfs
)... So this is not bash
anymore, but an alternative I guess is to use rsync
, here's an example:
编辑:...除了它似乎使我的服务器崩溃以获取远程 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
...
Note that:
注意:
- To get the above, you mustn't forget trailing slashes
/
at the end of directory names inrsync
--dry-run
- simulate only, don't update/transfer files-r
- recurse into directories-v
- verbose (but notrelated to file changes info)--cvs-exclude
- ignore.svn
files-i
- "--itemize-changes: output a change-summary for all updates"
- 要获得上述内容,您一定不要忘记
/
在目录名称末尾的斜杠rsync
--dry-run
- 仅模拟,不更新/传输文件-r
- 递归到目录-v
-详细(但不涉及到文件更改信息)--cvs-exclude
- 忽略.svn
文件-i
- “--itemize-changes:输出所有更新的变更摘要”
Here is a brief excerpt of man rsync
that explains the information shown by -i
(for instance, the >f.st......
strings above):
以下是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
....
A bit cryptic, indeed - but at least it shows basic directory comparison over ssh
. Cheers!
确实有点神秘 - 但至少它显示了ssh
. 干杯!
回答by Jonathan Leffler
The classic (System V Unix) answer would be dircmp dir1 dir2
, which was a shell script that would list files found in either dir1 but not dir2 or in dir2 but not dir1 at the start (first page of output, from the pr
command, so paginated with headings), followed by a comparison of each common file with an analysis (same, different, directory were the most common results).
经典的(System V Unix)答案是dircmp dir1 dir2
,这是一个 shell 脚本,它会列出在 dir1 但不是 dir2 或在 dir2 但不是 dir1 中找到的文件(输出的第一页,来自pr
命令,因此用标题分页),然后将每个常见文件与分析进行比较(相同、不同、目录是最常见的结果)。
This seems to be in the process of vanishing - I have an independent reimplementation of it available if you need it. It's not rocket science (cmp
is your friend).
这似乎正在消失 - 如果您需要,我可以对其进行独立的重新实现。这不是火箭科学(cmp
是你的朋友)。