234

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

4

15 回答 15

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

    command1 | command2
    

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

  2. -exec在 a 上find(这将做你想做的事——但特定于find

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

    find和之间的所有-exec内容都是您已经使用的查找谓词。 {}将替换您找到的特定文件到命令中(cat {}在这种情况下);即\;结束-exec命令。)

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

    command2 `command1`
    

    例如:

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

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

于 2009-05-14T16:30:15.900 回答
94

现代版

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

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

文件名问题是xargs没有-0选项的问题,“即使文件名为零也运行”问题是有或没有-0选项的问题——但 GNUxargs-ror--no-run-if-empty选项来防止这种情况发生。此外,此符号减少了进程的数量,而不是您可能会衡量性能差异。因此,您可以明智地写:

find . -exec grep something {} +

经典版

find . -print | xargs grep something

如果您在 Linux 上或拥有 GNUfindxargs命令,则使用-print0withfind-0withxargs来处理包含空格和其他奇数字符的文件名。

find . -print0 | xargs -0 grep something

调整结果grep

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

于 2009-05-14T16:21:57.870 回答
44

有几种方法可以将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 系统上,命令行长度限制非常大,因此与其他一些操作系统相比,拆分为多个调用非常罕见。

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

    find [whatever] | xargs cat
    

    xargs运行指定的命令(cat在本例中为 ),并根据从标准输入中读取的内容添加参数。就像-execwith一样+,这将在必要时分解命令行。也就是说,如果find产生过多的输出,它将运行cat多次。如前所述-exec,在某些命令中,这种拆分可能会导致不同的行为。请注意,xargs像这样使用在文件名中存在空格问题,因为xargs仅使用空格作为分隔符。

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

    find [whatever] -print0 | xargs -0 cat
    

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

于 2009-05-14T16:29:25.433 回答
10

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

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

这被称为“命令替换”,默认情况下会去除换行符,这真的很方便!

更多信息在这里

于 2012-09-12T16:27:49.143 回答
6

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

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

或类似的东西

于 2009-05-14T16:21:09.727 回答
4

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

find . -name \*.xml | while read i; do grep '<?xml' "$i" >/dev/null; [ $? == 0 ] && echo $i; done
于 2013-05-18T09:48:22.597 回答
3

这是我的一般用途镜头:

grep YOURSTRING `find .`

它将打印文件名

于 2012-05-30T13:53:50.770 回答
3

我使用这样的东西:

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

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

于 2016-11-30T11:29:46.650 回答
2

find 命令有一个 -exec 参数,您可以将其用于这样的事情,您可以直接使用它来执行 grep。

例如(从这里,此页面上的其他好例子):

find . -exec grep "www.athabasca" '{}' \; -print 
于 2009-05-14T16:22:10.067 回答
2

在 bash 中,以下是合适的:

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

这将找到目录中的所有文件,并将文件名安全/dir地通过管道传输到.xargsgrep

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

-print0参数与参数相结合find以正确处理带有空格的文件名。参数允许您在命令行中需要的位置插入文件名。括号被从.-0xargs-ixargscatcatfind

于 2011-04-14T11:17:44.903 回答
0

这对我有用

find _CACHE_* | while read line; do
    cat "$line" | grep "something"
done
于 2012-05-31T01:49:59.910 回答
0

使用ggrep

ggrep -H -R -I "mysearchstring" *

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

于 2013-02-21T04:50:23.047 回答
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 {} \;
于 2019-04-23T11:48:48.263 回答
-1

您是否尝试在文件中查找文本?你可以简单地使用 grep ......

grep searchterm *
于 2009-05-14T16:23:11.750 回答
-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 ^# {} \;
于 2010-03-21T03:51:39.490 回答