如何将 find 命令返回的文件列表用管道输送到 cat 以查看所有的文件。

我正在执行find以获取文件列表。

我如何将它管道到另一个实用程序,如cat,以便cat显示所有这些文件的内容?

然后,我将使用grep来搜索这些文件中的一些文本。

357359 次浏览

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

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

或者类似的东西

现代版

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

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

文件名问题是在没有-0选项的xargs中出现的问题,而“即使没有-0选项也会运行”问题是在没有-0选项的情况下出现的问题——但是GNU xargs-r--no-run-if-empty选项来防止这种情况发生。此外,这种表示法减少了进程的数量,并不是说您可能会度量性能上的差异。因此,你可以这样写:

find . -exec grep something {} +

经典的版本

find . -print | xargs grep something

如果你在Linux系统上,或者有GNU findxargs命令,那么使用-print0find,使用-0xargs来处理包含空格和其他奇怪字符的文件名。

find . -print0 | xargs -0 grep something

调整grep的结果

如果你不想要文件名(只是文本),那么在grep中添加一个适当的选项(通常是-h来抑制“标题”)。为了绝对保证文件名被grep打印出来(即使只找到一个文件,或者最后一次调用grep只给出了一个文件名),然后在xargs命令行中添加/dev/null,这样至少会有两个文件名。

find命令有一个-exec参数,你可以用它来做类似的事情,你可以直接用它来做grep。

例如(从这里开始,本页还有其他好的例子):

find . -exec grep "www.athabasca" '{}' \; -print

您正在尝试在文件中查找文本吗?你可以简单地使用grep…

grep searchterm *

有几种方法可以将find命令返回的文件列表传递给cat命令,尽管从技术上讲,并非所有方法都使用管道,而且实际上没有一种方法直接通过管道传递到cat

  1. 最简单的方法是使用反勾号(`):

    cat `find [whatever]`
    

    这将获取find的输出,并有效地将其放在cat的命令行上。如果find有太多的输出(超过了一个命令行可以容纳的数量),或者如果输出有特殊字符(如空格),这就不能很好地工作

  2. 在包括bash在内的一些shell中,可以使用$()来代替反引号:

    cat $(find [whatever])
    

    这是不太便携的,但可嵌套的。除此之外,它与反撇号有几乎相同的注意事项

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

    find [whatever] -exec cat {} \;
    

    {}是文件名的占位符,而\;标志着命令的结束(在-exec之后可能有其他操作)。

    这将为每个单独的文件运行cat一次,而不是运行cat的单个实例,传递多个文件名,这可能是低效的,并且可能没有你想要的某些命令的行为(尽管这对于cat是可以的)。语法也很难输入——您需要转义分号,因为分号对shell来说是特殊的!< / p >

  4. 某些版本的find(最著名的是GNU版本)允许你用+替换;,以使用-exec的追加模式来运行更少的cat实例:

    find [whatever] -exec cat {} +
    

    这将向cat的每次调用传递多个文件名,这可能更有效。

    注意,这是保证使用单一调用,然而。如果命令行太长,则参数将分布在cat的多次调用中。对于cat,这可能不是什么大问题,但对于其他一些命令,这可能会以不希望的方式改变行为。在Linux系统上,命令行长度限制相当大,因此与其他一些操作系统相比,拆分为多个调用是相当罕见的

  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+方法,虽然更可移植(但不幸的是更冗长)

  1. 管道到另一个进程(尽管这个不会完成了你说你正在尝试做的事情):

     command1 | command2
    

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

  2. -execfind(这将做你想做的,但它是特定于find):

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

    find-exec之间的所有东西都是你已经在使用的find谓词。{}将替换你在命令中找到的特定文件(在本例中是cat {});\;是结束-exec命令。

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

     command2 `command1`
    

    例如:

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

    注意这些是而不是普通的引号(它们在我键盘上的波浪号下面)。

    这将把command1的输出作为命令行参数发送到command2。它叫做命令替换。注意,包含空格(换行等)的文件名将被分解成单独的参数。

列出并查看服务器上/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 ^# {} \;

在bash中,以下代码是合适的:

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

这将找到/dir目录下的所有文件,并安全地将文件名管道到xargs中,这将安全地驱动grep

如果你在/dir中有成千上万的文件,跳过xargs不是一个好主意;cat将由于参数列表长度过大而中断。xargs将为您整理所有这些。

find-print0参数与xargs-0参数相匹配,以正确处理带有空格的文件名。xargs-i参数允许您在cat命令行中插入所需的文件名。括号由从find导入cat命令的文件名代替。

以下是我的常用镜头:

grep YOURSTRING `find .`

它将打印文件名

这对我很有用

find _CACHE_* | while read line; do
cat "$line" | grep "something"
done

为了实现这一点(使用bash),我将这样做:

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

这就是所谓的“命令替换”。而且它在默认情况下去掉换行,这真的很方便!

更多信息在这里

使用ggrep

ggrep -H -R -I "mysearchstring" *

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

下面是我找到包含一些我感兴趣的内容的文件名的方法,只是一个简单的bash行,很好地处理文件名中的空格:

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

我使用的方法是这样的:

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

“find”的“-print0”参数和“xargs”的“-0”参数需要正确处理文件路径/名称中的空白。

这将只递归地打印文件的名称和内容。

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

Edit(改进版本): 这将只递归地打印文本(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 {} \;