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

时间:2009-05-14 16:18:39

标签: unix find pipe

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

15 个答案:

答案 0 :(得分:298)

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

    command1 | command2
    

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

  2. -exec
  3. find(这将完成您想要做的事情 - 但具体针对find

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

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

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

    command2 `command1`
    

    例如:

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

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

答案 1 :(得分:78)

现代版

POSIX 2008将+标记添加到find,这意味着它现在会自动将尽可能多的文件分组到单个命令执行中,非常类似于xargs,但是优势数量:

  1. 您不必担心文件名中的奇数字符。
  2. 您不必担心使用零文件名调用命令。
  3. 文件名问题在xargs没有-0选项的情况下出现问题,而且“即使没有文件名运行”问题也存在问题,无论是否有-0选项 - 但GNU xargs具有-r--no-run-if-empty选项以防止发生这种情况。此外,这种表示法减少了进程数量,而不是您可能会衡量性能差异。因此,你可以明智地写道:

    find . -exec grep something {} +
    

    经典版

    find . -print | xargs grep something
    

    如果您使用的是Linux或拥有GNU findxargs命令,请将-print0find-0与{{1}一起使用处理包含空格和其他奇数球字符的文件名。

    xargs

    调整find . -print0 | xargs -0 grep something

    的结果

    如果您不想要文件名(只是文本),请向grep添加适当的选项(通常为grep以抑制'标题')。要绝对保证文件名由-h打印(即使只找到一个文件,或者最后一次调用grep只给出1个文件名),然后将grep添加到/dev/null命令行,以便始终至少有两个文件名。

答案 2 :(得分:34)

有几种方法可以将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),并根据从stdin读取的内容添加参数。就像-exec+一样,如果需要,这将打破命令行。也就是说,如果find产生太多输出,它将多次运行cat。正如之前关于-exec的部分所述,有些命令会导致此拆分可能导致不同的行为。请注意,使用xargs这样的文件名中存在空格问题,因为xargs只使用空格作为分隔符。

  6. 最强大,便携且高效的方法也使用xargs

    find [whatever] -print0 | xargs -0 cat
    

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

答案 3 :(得分:9)

为了达到这个目的(使用bash),我会这样做:

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

这就是所谓的“命令替换”,默认情况下它会删除换行符,这非常方便!

更多信息here

答案 4 :(得分:6)

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

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

或类似的东西

答案 5 :(得分:4)

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

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

答案 6 :(得分:3)

我使用这样的东西:

find . -name <filename> -print0 | xargs -0 cat | grep <word2search4>
为了正确处理文件路径/名称中的空格,需要“-print0”查询“查找”和“-0”参数“xargs”。

答案 7 :(得分:2)

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

例如(from here, other good examples at this page):

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

答案 8 :(得分:2)

在bash中,以下内容是合适的:

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

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

如果xargs中有数千个文件,则跳过/dir并不是一个好主意。由于参数列表长度过长,cat会中断。 xargs会为你排除这一切。

-print0的{​​{1}}参数与find的{​​{1}}参数相互作用,以正确处理带空格的文件名。 -0的{​​{1}}参数允许您在xargs命令行中的所需位置插入文件名。括号将替换为从-i发送到xargs命令的文件名。

答案 9 :(得分:2)

以下是我的一般用途:

grep YOURSTRING `find .`

它将打印文件名

答案 10 :(得分:0)

这对我有用

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

答案 11 :(得分:0)

使用ggrep

ggrep -H -R -I "mysearchstring" *

在包含位于当前目录或子目录

中的文本的unix中搜索文件

答案 12 :(得分:0)

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

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

答案 13 :(得分:-1)

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

grep searchterm *

答案 14 :(得分:-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 ^# {} \;