如何将find命令返回的文件列表传递给cat以查看所有文件

Dev*_*dar 194 unix pipe find

我正在做一个find然后获取文件列表.如何将其传输到另一个实用程序cat(以便cat显示所有这些文件的内容),并且基本上需要grep从这些文件中获取内容.

ken*_*418 320

  1. 管道到另一个过程(虽然这不会完成你所说的你想要做的事情):

    command1 | command2
    
    Run Code Online (Sandbox Code Playgroud)

    这将发送command1的输出作为command2的输入

  2. -exec在a find(这将做你想做的事 - 但具体到find)

    find . -name '*.foo' -exec cat {} \;
    
    Run Code Online (Sandbox Code Playgroud)

    (之间的一切find,并-exec在查找谓词你已经在使用, {}将取代你发现到命令的特定文件(cat {}在这种情况下);该\;是结束-exec.命令)

  3. 将一个进程的输出作为命令行参数发送到另一个进程

    command2 `command1`
    
    Run Code Online (Sandbox Code Playgroud)

    例如:

    cat `find . -name '*.foo' -print`
    
    Run Code Online (Sandbox Code Playgroud)

    (注意这些是BACK-QUOTES而不是常规引号(在我的键盘上的tilde~下).)这会将输出发送command1command2命令行参数.但请注意,包含空格(换行符等)的文件名将被分解为单独的参数.

  • 未提及:`找到.-name'*.foo'| xargs猫` (14认同)
  • 请注意,`find`的现代版本允许您编写:`find.-name'*.foo'-exec cat {} +`,其中`+`表示`find`应该将尽可能多的文件名分组到单个命令调用中.这非常有用(它处理文件名中的空格等而不依赖于`-print0`和`xargs -0`). (11认同)
  • cat`find -name'*.foo'-print`对我很有用...谢谢 (2认同)
  • 仅添加@stewSquared的答案:要查找文件中包含特定字符串的所有行,请执行`find。名称'* .foo'| xargs猫| grep字符串 (2认同)

Jon*_*ler 82

find . -exec grep something {} +
Run Code Online (Sandbox Code Playgroud)

如果你在Linux或有GNU +find,然后用xargsxargs,并-0具有-0处理包含空格和其他奇数球字符的文件名.

如果你不想要文件名 - 只是文本 - 那么添加一个合适的选项xargs(通常是-r为了抑制'标题').要绝对保证文件名是打印的--no-run-if-empty(即使只找到一个文件,或者最后一次调用find只给出1个文件名),然后添加xargs-print0命令行,这样总会至少有两个文件名.


请注意,POSIX 2008添加了find标记,-0这意味着它现在可以自动将尽可能多的文件分组到单个命令执行中,非常类似xargs,但具有许多优点:

  1. 您不必担心文件名中的奇数字符.
  2. 您不必担心使用零文件名调用命令.

这两个都是grep没有grep选项的问题.因此,你可以明智地写:

find . -print | xargs grep something
Run Code Online (Sandbox Code Playgroud)

  • @EricHu:我可以看到你很困惑,但它没有做你所说的,至少在我所知道的任何基于Unix的系统上都没有.`find`的输出通过管道输出到`xargs`的标准输入.`xargs`程序读取其标准输入,将输入分成白色空格(空格,换行符,制表符等),并将一些单词附加到命令`grep something`并执行命令行.`xargs`然后继续读取输入并执行命令,直到输入用完为止.`xargs`根据输入的需要经常运行`grep`命令(在本例中来自`find`). (3认同)

Lau*_*ves 34

有几种方法可以将find命令返回的文件列表传递给cat命令,虽然技术上并非全部都使用管道,但实际上没有一个直接管道cat.

  1. 最简单的是使用反引号(`):

    cat `find [whatever]`
    
    Run Code Online (Sandbox Code Playgroud)

    这需要输出find并有效地将其放在命令行上cat.如果find输出太多(超过可以放在命令行上)或者输出有特殊字符(如空格),则这不能很好地工作.

  2. 在某些shell中,包括bash,可以使用$()而不是反引号:

    cat $(find [whatever])
    
    Run Code Online (Sandbox Code Playgroud)

    这不太便携,但可以嵌套.除此之外,它与反引号几乎有相同的警告.

  3. 因为在找到的内容上运行其他命令是常用的find,所以find有一个-exec动作,它为它找到的每个文件执行一个命令:

    find [whatever] -exec cat {} \;
    
    Run Code Online (Sandbox Code Playgroud)

    {}是文件名的占位符,\;标记命令的结尾(之后可能有其他操作-exec.)

    这将为cat每个单个文件运行一次,而不是运行单个cat传递多个文件名的实例,这可能效率低下,并且可能没有您想要的某些命令的行为(尽管它很好cat).语法也是一个笨拙的类型 - 你需要转义分号,因为分号对shell来说是特殊的!

  4. 的某些版本find(最引人注目的是GNU版本)让你更换;+使用-exec的追加模式下运行的更少的情况下cat:

    find [whatever] -exec cat {} +
    
    Run Code Online (Sandbox Code Playgroud)

    这会将多个文件名传递给每次调用cat,这样可以更有效.

    但请注意,保证使用单个调用.如果命令行太长,那么参数将分布在多个调用中cat.因为cat这可能不是什么大问题,但对于其他一些命令,这可能会以不合需要的方式改变行为.在Linux系统上,命令行长度限制非常大,因此与其他一些操作系统相比,拆分为多个调用非常少见.

  5. 经典/便携式方法是使用xargs:

    find [whatever] | xargs cat
    
    Run Code Online (Sandbox Code Playgroud)

    xargs运行指定的命令(cat在本例中),并根据从stdin读取的内容添加参数.就像-exec+,这将在必要时向上突破的命令行.也就是说,如果find产生太多输出,它将运行cat多次.正如前面关于-exec前面部分所述,有一些命令会导致此拆分可能导致不同的行为.请注意,使用xargs这样的文件名中的空格有问题,因为xargs只使用空格作为分隔符.

  6. 最强大,最便携,最有效的方法还使用xargs:

    find [whatever] -print0 | xargs -0 cat
    
    Run Code Online (Sandbox Code Playgroud)

    -print0标志告诉在文件名之间find使用\0(空字符)分隔符,并且该-0标志告诉xargs期望这些\0分隔符.这与-exec... +方法具有完全相同的行为,但更便携(但不幸的是更冗长).


Stp*_*ane 9

要实现这一点(使用bash),我会这样做:

cat $(find . -name '*.foo')
Run Code Online (Sandbox Code Playgroud)

这被称为"命令替换",它默认剥离换行,这非常方便!

这里有更多的信息


Gan*_*alf 6

对我来说听起来像shell脚本的工作:

for file in 'find -name *.xml'
do
   grep 'hello' file
done
Run Code Online (Sandbox Code Playgroud)

或类似的东西

  • 这是一个有效的,但不一定是最佳的问题答案. (2认同)

小智 5

这是我查找包含一些我感兴趣的内容的文件名的方法,只需一个 bash 行就可以很好地处理文件名中的空格:

find . -name \*.xml | while read i; do grep '<?xml' "$i" >/dev/null; [ $? == 0 ] && echo $i; done
Run Code Online (Sandbox Code Playgroud)