Shell脚本以递归方式比较目录 [英] Shell script to compare directories recursively

查看:167
本文介绍了Shell脚本以递归方式比较目录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a file server backup on an external hard drive a few months old for a file server that went down since then. Most of the data was recovered onto a temporary file server thats been in use since then but there are some inconsistencies.

我将挂载外部并将其与当前数据同步,但是首先我需要建立在较新副本上已更新的文件。

I am going to mount the external and rsync it with the current data to it but first I need to establish files that have gotten updated on the newer copy.

我可以做diff -r -q / old / / new /来获得这个,我试图在脚本方面做得更好,所以我试图写一些东西来重命名旧的

I can do diff -r -q /old/ /new/ to obtain this, I am trying to get better at scripting so I am trying to write something that will rename the old file to filename.old whenever diff returns a difference.

推荐答案

因此,在检查后,我无法在 diff 仅输出文件名差异,因此我们将处理diff输出。

So after checking, I wasn't able to find an option in diff to only output the filename differences so we'll just work with what diff outputs.

如果 diff 查找不同的文件,输出如下所示:

If diff finds files that differ, the output is something like this:

Files old/file and new/file differ

由于您的所有bash脚本都会从中重命名更改后的文件旧目录,我们要从此输出中提取 old / file 。让我们从仅显示 Files ... differ 这样的行开始(可能会生成其他行):

Since all your bash script would be doing is renaming the changed file from the old directory, we want to extract old/file from this output. Let's start by only displaying lines like Files...differ (as other lines may be produced):

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

现在您将只获得如前所示的行。下一步是获取文件名。您可以使用 awk 来完成此操作,方法是添加 awk'{print $ 2}'作为另一个管道,但是如果文件名本身包含空格,awk会将其分解为两个单独的字符串。我们将改用sed:

Now you'll only get lines like the one shown before. Next step is getting the filename. You can do this with awk by adding something like awk '{print $2}' as another pipe but if the filename itself contains spaces, awk will break up that as two separate strings. We'll use sed instead:

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

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

Now this will produce a list of files that have changed in the old directory. Using a simple for loop, you can now rename each of the files:

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 会尝试生成一个默认情况下用空格分隔的列表。让我们将其更改为使用换行符:

edit: actually, that's not all. This loop still fails on files with spaces so let's muck with it a bit. for will try to produce a list separated by a space by default. Let's change this to use newlines instead:

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 )到换行符,并在完成循环后将其放回去,这样就不会按空格分割。

This temporarily replaces bash's default separator ($IFS) to a newline and puts it back after it's done with the loop so you don't split by space.

这篇关于Shell脚本以递归方式比较目录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆