shell脚本以递归方式比较目录

时间:2011-07-20 16:12:35

标签: bash shell diff

我在几个月前在外部硬盘驱动器上备份了一个文件服务器备份文件服务器。大多数数据被恢复到自那时以来一直在使用的临时文件服务器上,但存在一些不一致。

我将使用当前数据挂载外部和rsync,但首先我需要建立在较新副本上更新的文件。

我可以做diff -r -q / old / / new /来获得这个,我正在努力改进脚本,所以我试着写一些东西,只要diff返回一个就会将旧文件重命名为filename.old差。

2 个答案:

答案 0 :(得分:4)

所以在检查之后,我无法在diff中找到只输出文件名差异的选项,所以我们只会使用diff输出。

如果diff找到不同的文件,则输出如下:

Files old/file and new/file differ

由于您的所有bash脚本都在重命名旧目录中的已更改文件,因此我们希望从此输出中提取old/file。让我们首先只显示Files...differ之类的行(因为可能产生其他行):

diff -rq old/ new/ | grep "^Files.*differ$"

现在你只会获得前面所示的线条。下一步是获取文件名。您可以使用awk作为另一个管道添加awk '{print $2}'之类的内容,但如果文件名本身包含空格,则awk会将其分解为两个单独的字符串。我们将改用sed:

diff -rq old/ new/ | grep "^Files.*differ$" | sed 's/^Files \(.*\) and .* differ$/\1/'

现在,这将生成旧目录中已更改的文件列表。使用简单的for循环,您现在可以重命名每个文件:

for old_file in `diff -rq old/ new/ | grep "^Files.*differ$" | sed 's/^Files \(.*\) and .* differ$/\1/'`
do
   mv $old_file $old_file.old
done

就是这样!

编辑:实际上,这不是全部。这个循环在有空格的文件上仍然失败,所以让我们稍微捣乱它。 for默认会尝试生成一个由空格分隔的列表。让我们改变它来改为使用换行符:

OLD_IFS=$IFS
# The extra space after is crucial
IFS=\

for old_file in `diff -rq old/ new/ | grep "^Files.*differ$" | sed 's/^Files \(.*\) and .* differ$/\1/'`
do
   mv $old_file $old_file.old
done
IFS=$OLD_IFS

这暂时将bash的默认分隔符($IFS)替换为换行符,并在循环完成后将其重新放回,这样就不会按空格分割。

答案 1 :(得分:0)

曾经有一个潜伏在系统周围的程序dircmp。如果你有,请使用它。

如果您没有并且找不到它,那么我有一个可以使用的小版本的扩展版本(请参阅我的个人资料以获取联系信息)。

示例输出:

Files in ifxchkpath-4.12 only and in ifxchkpath-5.15 only

./Makefile                        ./absname.1
./program.mk                      ./absname.c
                                  ./chk.servers.sh
                                  ./chunklist.sh
                                  ./clnpath.c
                                  ./clnpath.h
                                  ./dirname.c
                                  ./enable.uids.sh
                                  ./errhelp.c
[...]
                                  ./lpt.pl
                                  ./makefile
                                  ./nvstrcpy.c
                                  ./realpath.c
                                  ./realpathtest.sh
                                  ./stderr.c
                                  ./stderr.h
                                  ./symlinks.tgz
                                  ./testids.mk
                                  ./test.linkpath.pl
                                  ./test.lpt.sh
                                  ./test.onsecurity.sh
                                  ./tokenise.c

Comparison of files in ifxchkpath-4.12 and ifxchkpath-5.15

directory           .
different           ./chk.ifxchkpath.sh
different           ./ifxchkpath.c
same                ./test.ifxchkpath.pl