我如何找到数百万个文件的目录diff来进行脚本维护



我一直在研究如何验证文件系统A上的数百万个文件实际上已移动到文件系统b。在进行系统迁移时,很明显需要审计所有文件以证明这些文件已被移动。这些文件最初是通过rsync移动的,rsync确实提供了日志,但不是一种有助于进行审计的格式。所以,我写了这个脚本来索引系统A上的所有文件:

#!/bin/bash
# Get directories and file list to be used to verify proper file moves have worked     successfully.
LOGDATE=`/usr/bin/date +%Y-%m-%d`
FILE_LIST_OUT=/mounts/A_files_$LOGDATE.txt
MOUNT_POINTS="/mounts/AA mounts/AB"
touch $FILE_LIST_OUT 
echo TYPE,USER,GROUP,BYTES,OCTAL,OCTETS,FILE_NAME > $FILE_LIST_OUT
for directory in $MOUNT_POINTS; do
    # format: type,user,group,bytes,octal,octets,file_name
    gfind $directory -mount -printf "%y","%u","%g","%s","%m","%pn" >> $FILE_LIST_OUT
done

文件索引工作良好,大约需要两个小时索引~ 3000万个文件。

B面是我们遇到问题的地方。我编写了一个非常简单的shell脚本,它读取索引文件,测试文件是否在那里,然后计算有多少文件在那里,但是在遍历索引文件名的3000万行时,它耗尽了内存。通过while循环有效地执行下面的一小段代码,并为找到和未找到的文件增加计数器。

if [ -f "$TYPE" "$FILENAME" ] ; then
print file found 
++
else 
file not found 
++
fi

我的问题是:

  1. 一个shell脚本可以从这么大的列表中做这种类型的报告吗?64位unix系统在尝试执行此脚本时内存不足。我已经考虑过将输入脚本分解成更小的块以使其更快。目前可以
  2. 如果作为shell脚本是不合适的,你会建议什么?

你刚用过rsync,再用一次…

——ignore-existing

这告诉rsync跳过更新目标上已经存在的文件(这不会忽略现有的目录,否则什么都不会做)。参见——existing.

这个选项是一个传输规则,而不是一个排除规则,所以它不会影响进入文件列表的数据,因此它不会影响删除。它只是限制了接收方请求传输的文件。

对于那些使用——link-dest选项进行备份的人来说,当他们需要继续被中断的备份运行时,这个选项可能很有用。由于——link-dest运行被复制到一个新的目录层次结构中(当它被正确使用时),使用——ignore existing将确保已经处理的文件不会被调整(这避免了对硬链接文件的权限更改)。这意味着该选项只查看目标层次结构本身中的现有文件。

这将实际修复任何问题(至少在相同的意义上,文件存在测试上的任何差异列表都可以修复问题)。使用--ignore-existing意味着rsync只执行文件存在测试(因此它将根据您的请求构建diff列表并在内部使用它)。如果您只想了解不同之处,请查看--dry-run--itemize-changes

假设你有两个目录,foobar。假设bar有三个文件:123。假设bar有一个目录quz,该目录有一个文件1。目录foo为空:

结果如下,

$ rsync -ri --dry-run --ignore-existing ./bar/ ./foo/
>f+++++++++ 1
>f+++++++++ 2
>f+++++++++ 3
cd+++++++++ quz/
>f+++++++++ quz/1

注意,您对cd+++++++++不感兴趣——这只是向您显示rsync发出了chdir。现在,让我们在foo中添加一个名为1的文件,并使用grep删除chdir (s)

$ rsync -ri --dry-run --ignore-existing ./bar/ ./foo/ | grep -v '^cd'
>f+++++++++ 2
>f+++++++++ 3
>f+++++++++ quz/1

f表示文件。+++++++++表示该文件在DEST目录中不存在。

这是额外的,删除--dry-run,它会继续为你做更改。

您是否考虑过像kdiff3这样的解决方案,它将对文件目录进行diff ?

注意0.9.84版本的特性

Directory-Comparison:选项"Full Analysis"允许显示数字已解决的冲突与未解决的冲突或增量与空白的变化目录树

  1. 在shell脚本中读取一个3000万行的文件绝对没有问题。你的进程失败的原因很可能是你试图将文件完全读取到内存中,例如通过做一些错误的事情,如for i in $(cat file)。读取文件的正确方法是:

    while IFS= read -r line
      do
        echo "Something with $line"
    done < someFile
    
  2. shell脚本是不合适的,是的。您应该使用diff工具:

    diff -rNq /original /new
    

如果您对脚本解决方案不太在意,您还可以查看meld,它可以让您轻松地区分目录树,并且如果您有任何模式,您还可以设置忽略模式。

最新更新