代码之家  ›  专栏  ›  技术社区  ›  Vinko Vrsalovic

在bash中工作时,如何处理“文件太多”问题?

  •  6
  • Vinko Vrsalovic  · 技术社区  · 16 年前

    我经常需要处理包含数十万个文件的目录,进行文本匹配、替换等等。如果我走的是标准路线,比如

    grep foo *
    

    我收到了太多的文件错误消息,所以我最终做了

    for i in *; do grep foo $i; done
    

    find ../path/ | xargs -I{} grep foo "{}"
    

    但这些都不是最佳的(为每个文件创建一个新的grep进程)。

    这看起来更像是程序可以接收的参数大小的限制,因为for循环中的*工作正常。但是,无论如何,处理这个问题的正确方法是什么?

    PS:不要告诉我做grep-r,我知道,我在考虑没有递归选项的工具。

    5 回复  |  直到 9 年前
        1
  •  8
  •   Charles Duffy    9 年前

    在新版本的findutils中,find可以执行xargs的工作(包括肾小球行为,例如只使用所需的grep进程):

    find ../path -exec grep foo '{}' +
    

    使用 + 而不是 ; 最后一个参数触发此行为。

        2
  •  6
  •   JesperE    16 年前

    如果存在包含空格的文件名风险,请记住使用-print0标志与-0标志一起查找xargs:

    find . -print0 | xargs -0 grep -H foo
    
        3
  •  4
  •   camh    16 年前

    xargs不会为每个文件启动新的进程。它把各种论点聚在一起。查看xargs的-n选项,它控制传递给子命令每次执行的参数数量。

        4
  •  0
  •   paxdiablo    16 年前

    我看不出来

    for i in *; do
        grep foo $i
    done
    

    因为我认为“太多的文件”是一个shell限制,所以它也会在for循环中失败。

    我已经说过了,我总是让xargs做一些咕哝的工作,将参数列表拆分为可管理的位,这样:

    find ../path/ | xargs grep foo
    

    它不会为每个文件启动进程,而是为每个文件组启动进程。

        5
  •  0
  •   whoan    9 年前

    嗯,我也有同样的问题,但似乎我想出来的每件事都已经提到了。主要有两个问题。在一百万个文件目录上执行ls需要花费很长时间(在我的一个服务器上需要20分钟以上),而在一百万个文件目录上执行ls*则需要花费很长时间,并且会因“参数列表太长”错误而失败。

    find /some -type f -exec some command {} \; 
    

    似乎有助于解决这两个问题。另外,如果您需要对这些文件执行更复杂的操作,您可以考虑将您的东西编写成多个线程。这里有一个用于编写cli脚本的python入门。 http://www.ibm.com/developerworks/aix/library/au-pythocli/?ca=dgr-lnxw06pythonunixtool&S_TACT=105AGX59&S_CMP=GR