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


204

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

Answers:


340
  1. 传递到另一个进程(尽管这不会完成您说的那样):

    command1 | command2
    

    这将发送命令1的输出作为命令2的输入

  2. -execfind(这将完成您想做的-但特定于find

    find . -name '*.foo' -exec cat {} \;
    

    find和之间的所有内容-exec都是您已在使用的查找谓词。 {}它将您找到的特定文件替换为命令(cat {}在本例中为);\;是结束-exec命令。)

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

    command2 `command1`
    

    例如:

    cat `find . -name '*.foo' -print`
    

    (注意,这些都是反引号不正规报价(我的键盘上的波浪线〜之下)。)这将输出发送command1command2作为命令行参数。请注意,包含空格(换行符等)的文件名将分成单独的参数。


2
find -name '*.foo' -print对我非常
有用

反引号可以很好地工作并且更通用,您也可以使用它来从文件中列出文件列表。
Hazok 2011年

11
请注意,现代版本的find允许您编写:find . -name '*.foo' -exec cat {} +,其中的+表示find应将尽可能方便的文件名分组为单个命令调用。这非常有用(它无需使用-print0and 即可处理文件名中的空格等xargs -0)。
乔纳森·勒夫勒

18
未提及:find . -name '*.foo' | xargs cat
stewSquared

3
只需添加@stewSquared的答案即可:要查找文件中包含特定字符串的所有行,请执行find . -name '*.foo' | xargs cat | grep string
Bim

84

现代版本

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

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

文件名问题是xargs不带-0选项的问题,而“即使文件名为零也可以运行”问题是带或不带-0选项的问题-但是GNU xargs具有-r--no-run-if-empty选项来防止这种情况的发生。而且,此表示法减少了进程数,而不是您可能要衡量性能差异。因此,您可以明智地编写:

find . -exec grep something {} +

经典版

find . -print | xargs grep something

如果您使用的是Linux或具有GNU findxargs命令,则使用-print0with find-0with xargs处理包含空格和其他奇数字符的文件名。

find . -print0 | xargs -0 grep something

调整来自的结果 grep

如果您不希望使用文件名(仅文本),则添加一个适当的选项grep(通常-h是禁止显示“标题”)。为了绝对保证文件名的打印方式grep(即使仅找到一个文件,或者最后一次调用grep仅给出1个文件名),然后将其添加/dev/nullxargs命令行中,以便始终至少有两个文件名。


对于像我这样困惑的人,请注意,这种方式将首先给出find的所有输出,然后给出的输出xargs grep something
艾瑞克·胡

3
@EricHu:我可以看到您感到困惑,但是它并没有按照您所说的去做,至少在我所知道的任何基于Unix的系统上都没有。的输出通过find管道传递到的标准输入xargs。该xargs程序读取它的标准输入,在白空间分割输入(空格,新行,制表符,等),并附加一个数字的话到命令grep something并执行该命令行。xargs然后继续读取输入并执行命令,直到输入用完。根据给出的输入,尽可能多地xargs运行grep命令(find在此示例中)。
Jonathan Leffler

啊,我的错,这是使用grep在匹配的每个文件中进行搜索。我当时只是想简单地使用grep过滤find的输出
Eric Hu

1
在所有行为良好的命令上,错误都变为标准错误(文件描述符2)。将stderr重定向到/dev/null会丢失错误消息。
Jonathan Leffler

1
这还有一个好处,就是可以更好地处理文件路径中的空格。甚至'sed'ing“”->“ \”都会用`破坏它,但使用xargs则可以完美工作
JZL003 2014年

36

有几种方法可以将find命令返回的文件列表传递给cat命令,尽管从技术上讲并不是全部使用管道,也没有一种方法直接将管道直接传递给cat

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

    cat `find [whatever]`
    

    这将获取的输出find并将其有效地放置在的命令行上cat。如果find输出过多(超出命令行的大小)或输出具有特殊字符(如空格),则此方法将无法正常工作。

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

    cat $(find [whatever])
    

    这不太方便携带,但可以嵌套。除此之外,它还有与反引号相同的警告。

  3. 因为在找到的内容上运行其他命令是的常见用法find,find具有一个-exec操作,它针对找​​到的每个文件执行一个命令:

    find [whatever] -exec cat {} \;
    

    {}是文件名的占位符,和\;该命令的结束标记(这是可能有后其他动作-exec。)

    这将对cat每个文件运行一次,而不是运行cat向其传递多个文件名的单个实例,这可能效率低下,并且可能没有某些命令所希望的行为(尽管可以使用cat)。语法也很难输入-您需要转义分号,因为分号是shell特有的!

  4. 的某些版本find(最引人注目的是GNU版本)让你更换;+到使用-exec的附加模式运行的实例少cat

    find [whatever] -exec cat {} +
    

    这将通过多个文件名到的每次调用cat,其可以是更有效的。

    请注意,但这不能保证使用单个调用。如果命令行太长,则参数分布在的多个调用中cat。因为cat这可能没什么大不了的,但是对于某些其他命令,这可能会以不希望的方式更改行为。在Linux系统上,命令行长度限制非常大,因此与其他某些OS相比,分成多个调用的情况很少见。

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

    find [whatever] | xargs cat
    

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

  6. 最健壮,便携式和高效的方法还使用xargs

    find [whatever] -print0 | xargs -0 cat
    

    -print0标志指示在文件名之间find使用\0(空字符)定界符,并且-0标志指示xargs期望这些\0定界符。这种行为与-exec... +方法几乎具有相同的行为,但更便于携带(但不幸的是更冗长)。


backtick方法很棒,因为它也适用于其他命令,例如ls
马丁·布劳恩

@Martin Braun使用 $()也可用于以外的命令find
劳伦斯·贡萨尔维斯

谢谢,很高兴知道,我有点停止阅读(1)之后的内容,因为它满足了我的需要,因为我不处理空格等特殊字符。
马丁·布劳恩

9

为了实现这一点(使用bash),我将执行以下操作:

cat $(find . -name '*.foo')

这就是所谓的“命令替换”,默认情况下它会剥去换行符,这确实很方便!

更多信息在这里


6

听起来对我来说,shell脚本是一项工作:

for file in 'find -name *.xml'
do
   grep 'hello' file
done

或类似的东西


2
这是对问题的有效答案,尽管不一定是最佳答案。
乔纳森·勒夫勒

1
...是的,但是如果您还想要一个列出文件名的大文件,那就太好了。
2011年

1
我最喜欢这个。这样的循环块留出了做其他事情的空间。
kakyo

4

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

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

3

我用这样的东西:

find . -name <filename> -print0 | xargs -0 cat | grep <word2search4>

-print0为了-0正确处理文件路径/名称中的空格,需要使用“ ”的“ find” 参数和“ ”的“ xargs”参数。



2

这是我一般使用的镜头:

grep YOURSTRING `find .`

它将打印文件名


2

在bash中,以下内容比较合适:

find /dir -type f -print0 | xargs -0i cat {} | grep whatever

这将在/dir目录中找到所有文件,并安全地将文件名输送到xargs,这些文件名将安全地驱动器grep

xargs如果您有成千上万个文件,则跳过不是一个好主意/dircat将由于参数列表长度过长而中断。xargs将为您解决所有问题。

-print0参数find与的-0参数啮合以xargs正确处理带有空格的文件名。该-i给的说法xargs让你插入在需要的文件名cat的命令行。括号被替换为cat从中传递到命令的文件名find



0

使用ggrep

ggrep -H -R -I "mysearchstring" *

在unix中搜索包含位于当前目录或子目录中的文本的文件


0

这将以递归方式仅打印文件的名称和内容。

find . -type f -printf '\n\n%p:\n' -exec cat {} \;

编辑(改进版本): 这将仅递归打印文本(ascii)文件的名称和内容。

find . -type f -exec grep -Iq . {} \; -print | xargs awk 'FNR==1{print FILENAME ":" $0; }'

再尝试一次

find . -type f -exec grep -Iq . {} \; -printf "\n%p:" -exec cat {} \;


-1

列出并查看目录/ ghi和/ jkl中服务器上所有abc.def文件的内容

find /ghi /jkl -type f -name abc.def 2> /dev/null -exec ls {} \; -exec cat {} \;

要列出具有注释条目并显示的abc.def文件,请在目录/ ghi和/ jkl中查看这些条目

find /ghi /jkl -type f -name abc.def 2> /dev/null -exec grep -H ^# {} \;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.