【问题标题】:fast shell find快速查找外壳
【发布时间】:2012-04-11 17:34:50
【问题描述】:

我有一个简单的查找命令,它需要遍历服务器上的数百万个文件并找到一些具有给定后缀的文件。随着时间的推移,这些文件被频繁地写入和删除。我只是想知道是否有一种方法可以更快地找到。使用 locate 是没有问题的,因为为 locate 制作数据库将非常昂贵。

find /myDirWithThausandsofDirectories/ -name *.suffix

在某些服务器上,此命令需要几天时间!

有什么想法吗?

谢谢,

【问题讨论】:

  • 这就是你所能做的。 find 将为您迭代目录,但是由于目录条目的存储方式,遍历 unix 系统上的“大”目录自然会很慢。
  • 解决问题? find /myDirWith../dira* -name *.suf & find /myDirWith../dirb* -name *.suf ....& 另外,看看gnu-parallelxargs -n 祝你好运!
  • 也许拥有与数百万个文件不同的东西是一个很好的例子,例如GDBM 数据库,或 MySQL 或 PostGresQL 等“关系”数据库,或 mangodb 等 noSQL 数据库。

标签: linux shell find


【解决方案1】:

您可以使用审计子系统来监控文件的创建和删除。将此与find 的初始运行相结合,您应该可以创建一个可以实时更新的文件数据库。

【讨论】:

    【解决方案2】:

    分而治之?假设 MP 操作系统和处理器 为每个子文件夹生成多个 find 命令。

    for dir in /myDirWithThausandsofDirectories/*
    do find "$dir" -name "*.suffix" &
    done
    

    根据子目录的数量,您可能希望控制在给定时间运行的进程数(find 命令)。这将有点棘手,但可行(即使用 bash shell,使用生成的进程$! 的 pid 保留一个数组,并且只允许新进程,具体取决于数组的长度)。 上面也没有搜索根目录下的文件,只是一个简单的例子。

    如果您不知道如何完成流程管理,那么是时候学习了;) This 是关于该主题的非常好的文本。 This 是您实际需要的。但请阅读整篇文章以了解其工作原理。

    【讨论】:

    • 您还可以查看 niceionice 之类的内容,以便为您的脚本提供更高的优先级,但我不确定这是否会产生很大的不同,并且很可能会使机器无法用于其他用途。
    • 不知道怎么控制进程数!
    【解决方案3】:

    由于您使用的是简单的 glob,您也许可以使用 Bash 的递归 glob。示例:

    shopt -s globstar
    for path in /etc/**/**.conf
    do
        echo "$path"
    done
    

    可能会更快,因为它使用的是内部 shell 功能,其灵活性远低于 find

    如果你不能使用 Bash,但你对路径深度有限制,你可以明确列出不同的深度:

    for path in /etc/*/*.conf /etc/*/*/*.conf /etc/*/*/*/*.conf
    do
        echo "$path"
    done
    

    【讨论】:

      【解决方案4】:

      代码如下:

      find /myDirWithThausandsofDirectories/ -d type maxdepth 1 > /tmp/input
      IFS=$'\n' read -r -d '' -a files < /tmp/input
      
      
      do_it() {
         for f; do find $f  -name *.suffix | sed -e s/\.suffix//g ; done
      }
      
      # Divide the list into 5 sub-lists.
      i=0 n=0 a=() b=() c=() d=() e=()
      while ((i < ${#files[*]})); do
          a[n]=${files[i]}
          b[n]=${files[i+1]}
          c[n]=${files[i+2]}
          d[n]=${files[i+3]}
          e[n]=${files[i+4]}
          ((i+=5, n++))
      done
      
      # Process the sub-lists in parallel
      do_it "${a[@]}" >> /tmp/f.unsorted 2>/tmp/f.err &
      do_it "${b[@]}" >> /tmp/f.unsorted 2>/tmp/f.err &
      do_it "${c[@]}" >> /tmp/f.unsorted 2>/tmp/f.err &
      do_it "${d[@]}" >> /tmp/f.unsorted 2>/tmp/f.err &
      do_it "${e[@]}" >> /tmp/f.unsorted 2>/tmp/f.err &
      wait
      echo Find is Done!
      

      我遇到的唯一问题是一些文件名(非常小的百分比)部分出现。我不知道是什么原因!

      【讨论】: