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

时间:2013-02-26 21:12:26

标签: shell directory

我一直在研究如何验证文件系统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. 如果shell脚本不合适,您会建议什么?

4 个答案:

答案 0 :(得分:1)

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

  

<强> - 忽略-现有

     

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

     

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

     

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

这实际上会解决任何问题(至少在同一意义上,文件存在的测试中的任何差异列表都可以解决问题。使用--ignore-existing意味着rsync只进行文件存在的测试(因此,它会根据您的请求构建差异列表并在内部使用它。如果您只想了解差异的信息,请检查--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}}中添加一个文件,让我们使用1删除grep

chdir

f 适用于档案。 ++++++++++++++++++++++

这是奖金,删除$ rsync -ri --dry-run --ignore-existing ./bar/ ./foo/ | grep -v '^cd' >f+++++++++ 2 >f+++++++++ 3 >f+++++++++ quz/1 ,然后它会继续为您做出更改。

答案 1 :(得分:0)

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

请注意版本0.9.84的功能

  

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

答案 2 :(得分:0)

  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
    

答案 3 :(得分:0)

如果您不是特别关注该解决方案是一个脚本,您还可以查看meld,它可以让您轻松地对目录树进行区分,如果您有任何设置,也可以设置忽略模式。