递归比较目录的 Shell 脚本

发布于 2024-11-25 10:10:53 字数 237 浏览 1 评论 0原文

我在几个月前的外部硬盘驱动器上有一个文件服务器备份,用于从那时起就出现故障的文件服务器。大部分数据已恢复到此后一直使用的临时文件服务器上,但存在一些不一致之处。

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

我可以做 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一世旳自豪 2024-12-02 10:10:53

因此,经过检查,我无法在 diff 中找到仅输出文件名差异的选项,因此我们将仅使用 diff 输出的内容。

如果 diff 发现不同的文件,则输出如下所示:

Files old/file and new/file differ

由于 bash 脚本要做的就是从旧目录中重命名已更改的文件,因此我们要提取 old/file< /code> 来自此输出。让我们首先只显示像 Files...differ 这样的行(因为可能会生成其他行):

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

现在您只会得到与之前显示的行类似的行。下一步是获取文件名。您可以通过添加诸如 awk '{print $2}' 之类的内容作为另一个管道,使用 awk 来完成此操作,但如果文件名本身包含空格,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) 替换为换行符,并在循环完成后将其放回原处,这样就不会被空格分割。

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:

Files old/file and new/file 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$"

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/'

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

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:

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

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.

不打扰别人 2024-12-02 10:10:53

曾经有一个程序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

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:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文