递归比较目录的 Shell 脚本
我在几个月前的外部硬盘驱动器上有一个文件服务器备份,用于从那时起就出现故障的文件服务器。大部分数据已恢复到此后一直使用的临时文件服务器上,但存在一些不一致之处。
我将安装外部并将其与当前数据同步,但首先我需要建立已在较新副本上更新的文件。
我可以做 diff -r -q /old/ /new/ 来获得这个,我试图更好地编写脚本,所以我试图编写一些东西,每当 diff 返回差异时,将旧文件重命名为 filename.old 。
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.
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
因此,经过检查,我无法在
diff
中找到仅输出文件名差异的选项,因此我们将仅使用 diff 输出的内容。如果
diff
发现不同的文件,则输出如下所示:由于 bash 脚本要做的就是从旧目录中重命名已更改的文件,因此我们要提取
old/file< /code> 来自此输出。让我们首先只显示像
Files...differ
这样的行(因为可能会生成其他行):现在您只会得到与之前显示的行类似的行。下一步是获取文件名。您可以通过添加诸如
awk '{print $2}'
之类的内容作为另一个管道,使用 awk 来完成此操作,但如果文件名本身包含空格,awk 会将其分解为两个单独的管道字符串。我们将使用 sed 来代替:现在这将生成旧目录中已更改的文件列表。使用简单的 for 循环,您现在可以重命名每个文件:
就是这样!
编辑:实际上,这还不是全部。这个循环在带有空格的文件上仍然失败,所以让我们稍微处理一下。
for
默认情况下会尝试生成一个以空格分隔的列表。让我们将其更改为使用换行符:这会暂时将 bash 的默认分隔符 (
$IFS
) 替换为换行符,并在循环完成后将其放回原处,这样就不会被空格分割。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.If
diff
finds files that differ, the output is something like this: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 likeFiles...differ
(as other lines may be produced):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 likeawk '{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: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:
And that's it!
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: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.曾经有一个程序
dircmp
潜伏在系统周围。如果你有它,请使用它。如果您没有并且找不到它,那么我有一个带有较小扩展的版本供您使用(请参阅我的个人资料以获取联系信息)。
输出示例:
There used to be a program
dircmp
lurking around systems. If you have it, use it.If you don't have and can't find it, then I have a version of it with minor extensions that you can use (see my profile for contact information).
Example output: