1

我一直在研究如何验证文件系统 A 上的数百万个文件实际上是否已移动到文件系统 B。在进行系统迁移时,很明显需要审核所有文件以证明文件已被移动。这些文件最初是通过 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","%p\n" >> $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. 如果 as shell 脚本不合适,你会建议什么?
4

4 回答 4

1

您刚刚使用了 rsync,再次使用它...

--忽略现有

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

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

当需要继续中断的备份运行时,此选项对于使用 --link-dest 选项进行备份的人非常有用。由于 --link-dest 运行被复制到一个新的目录层次结构中(当它被正确使用时),使用 --ignore existing 将确保已经处理的文件不会被调整(这避免了对硬链接文件)。这确实意味着此选项仅查看目标层次结构本身中的现有文件。

这实际上会解决任何问题(至少在相同意义上,文件存在测试上的任何差异列表都可以解决问题。使用--ignore-existing意味着rsync只执行文件存在测试(因此它会在您请求和使用时构建差异列表)它在内部)。如果您只需要有关差异的信息,请检查--dry-run--itemize-changes

假设您有两个目录,foo并且bar. 假设bar有三个文件,1,23. 比方说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. 现在,让我们在foocalled中添加一个文件1,并让我们使用grep删除chdir(s),

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

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

这是奖金, remove --dry-run,它会继续为您进行更改。

于 2013-02-26T21:34:26.453 回答
0

您是否考虑过诸如kdiff3之类的解决方案,它将区分文件目录?

请注意版本 0.9.84 的功能

目录比较:选项“完整分析”允许显示目录树中已解决与未解决的冲突或增量与空白更改的数量。

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

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

    diff -rNq /original /new
    
于 2013-02-26T21:22:08.697 回答
0

如果您不特别关注作为脚本的解决方案,您还可以查看meld,它可以让您非常轻松地区分目录树,如果有的话,您还可以设置忽略模式。

于 2013-02-26T21:37:01.890 回答