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

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

  •  7
  • 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 回复  |  直到 16 年前
        1
  •  8
  •   Charles Duffy    9 年前

    在findutils的较新版本中,find可以完成xargs的工作(包括glomming行为,这样就可以根据需要使用尽可能多的grep进程):

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

    使用 + 而不是 ; 因为最后一个参数会触发这种行为。

        2
  •  6
  •   JesperE    16 年前

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

    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 年前

    好吧,我也有同样的问题,但似乎我想到的一切都已经提到了。主要有两个问题。执行globs是昂贵的,在一百万个文件目录上执行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