Shell脚本以递归方式比较目录 [英] Shell script to compare directories recursively
问题描述
我在几个月前使用的外部硬盘驱动器上备份了文件服务器,此后该文件服务器已关闭。自那时以来,大多数数据已恢复到使用的临时文件服务器上,但存在一些不一致之处。
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屋!