我正在做一个find
,然后获取文件列表。我如何将其通过管道传输到另一个实用程序cat
(例如,cat显示所有这些文件的内容),并且基本上需要grep
这些文件中的某些内容。
我正在做一个find
,然后获取文件列表。我如何将其通过管道传输到另一个实用程序cat
(例如,cat显示所有这些文件的内容),并且基本上需要grep
这些文件中的某些内容。
Answers:
传递到另一个进程(尽管这不会完成您说的那样):
command1 | command2
这将发送命令1的输出作为命令2的输入
-exec
上find
(这将完成您想做的-但特定于find
)
find . -name '*.foo' -exec cat {} \;
(find
和之间的所有内容-exec
都是您已在使用的查找谓词。 {}
它将您找到的特定文件替换为命令(cat {}
在本例中为);\;
是结束-exec
命令。)
将一个进程的输出作为命令行参数发送到另一进程
command2 `command1`
例如:
cat `find . -name '*.foo' -print`
(注意,这些都是反引号不正规报价(我的键盘上的波浪线〜之下)。)这将输出发送command1
到command2
作为命令行参数。请注意,包含空格(换行符等)的文件名将分成单独的参数。
find
允许您编写:find . -name '*.foo' -exec cat {} +
,其中的+
表示find
应将尽可能方便的文件名分组为单个命令调用。这非常有用(它无需使用-print0
and 即可处理文件名中的空格等xargs -0
)。
find . -name '*.foo' | xargs cat
find . -name '*.foo' | xargs cat | grep string
POSIX 2008添加了+
标记,find
这意味着它现在可以自动将尽可能多的文件分组到一个命令执行中,这非常相似xargs
,但是具有许多优点:
文件名问题是xargs
不带-0
选项的问题,而“即使文件名为零也可以运行”问题是带或不带-0
选项的问题-但是GNU xargs
具有-r
或--no-run-if-empty
选项来防止这种情况的发生。而且,此表示法减少了进程数,而不是您可能要衡量性能差异。因此,您可以明智地编写:
find . -exec grep something {} +
find . -print | xargs grep something
如果您使用的是Linux或具有GNU find
和xargs
命令,则使用-print0
with find
和-0
with xargs
处理包含空格和其他奇数字符的文件名。
find . -print0 | xargs -0 grep something
grep
如果您不希望使用文件名(仅文本),则添加一个适当的选项grep
(通常-h
是禁止显示“标题”)。为了绝对保证文件名的打印方式grep
(即使仅找到一个文件,或者最后一次调用grep
仅给出1个文件名),然后将其添加/dev/null
到xargs
命令行中,以便始终至少有两个文件名。
xargs grep something
。
find
管道传递到的标准输入xargs
。该xargs
程序读取它的标准输入,在白空间分割输入(空格,新行,制表符,等),并附加一个数字的话到命令grep something
并执行该命令行。xargs
然后继续读取输入并执行命令,直到输入用完。根据给出的输入,尽可能多地xargs
运行grep
命令(find
在此示例中)。
/dev/null
会丢失错误消息。
有几种方法可以将find
命令返回的文件列表传递给cat
命令,尽管从技术上讲并不是全部使用管道,也没有一种方法直接将管道直接传递给cat
。
最简单的是使用反引号(`
):
cat `find [whatever]`
这将获取的输出find
并将其有效地放置在的命令行上cat
。如果find
输出过多(超出命令行的大小)或输出具有特殊字符(如空格),则此方法将无法正常工作。
在包括在内的某些shell中,bash
可以使用$()
而不是反引号:
cat $(find [whatever])
这不太方便携带,但可以嵌套。除此之外,它还有与反引号相同的警告。
因为在找到的内容上运行其他命令是的常见用法find
,find具有一个-exec
操作,它针对找到的每个文件执行一个命令:
find [whatever] -exec cat {} \;
的{}
是文件名的占位符,和\;
该命令的结束标记(这是可能有后其他动作-exec
。)
这将对cat
每个文件运行一次,而不是运行cat
向其传递多个文件名的单个实例,这可能效率低下,并且可能没有某些命令所希望的行为(尽管可以使用cat
)。语法也很难输入-您需要转义分号,因为分号是shell特有的!
的某些版本find
(最引人注目的是GNU版本)让你更换;
与+
到使用-exec
的附加模式运行的实例少cat
:
find [whatever] -exec cat {} +
这将通过多个文件名到的每次调用cat
,其可以是更有效的。
请注意,但这不能保证使用单个调用。如果命令行太长,则参数分布在的多个调用中cat
。因为cat
这可能没什么大不了的,但是对于某些其他命令,这可能会以不希望的方式更改行为。在Linux系统上,命令行长度限制非常大,因此与其他某些OS相比,分成多个调用的情况很少见。
经典/便携式方法是使用xargs
:
find [whatever] | xargs cat
xargs
运行指定的命令(cat
在这种情况下为),并根据从stdin中读取的内容添加参数。就像-exec
用+
,这将在必要时向上突破的命令行。也就是说,如果find
产生太多输出,它将运行cat
多次。如前一节所述-exec
,有一些命令可能会导致这种行为不同。请注意,xargs
像这样使用时,文件名中的空格会出现问题,xargs
就像使用空格作为分隔符一样。
最健壮,便携式和高效的方法还使用xargs
:
find [whatever] -print0 | xargs -0 cat
该-print0
标志指示在文件名之间find
使用\0
(空字符)定界符,并且-0
标志指示xargs
期望这些\0
定界符。这种行为与-exec
... +
方法几乎具有相同的行为,但更便于携带(但不幸的是更冗长)。
ls
。
$()
也可用于以外的命令find
。
find命令具有-exec参数,您可以将其用于诸如此类的事情,您可以直接使用它来执行grep。
例如(从此处,此页面上的其他好示例):
find . -exec grep "www.athabasca" '{}' \; -print
在bash中,以下内容比较合适:
find /dir -type f -print0 | xargs -0i cat {} | grep whatever
这将在/dir
目录中找到所有文件,并安全地将文件名输送到xargs
,这些文件名将安全地驱动器grep
。
xargs
如果您有成千上万个文件,则跳过不是一个好主意/dir
;cat
将由于参数列表长度过长而中断。xargs
将为您解决所有问题。
的-print0
参数find
与的-0
参数啮合以xargs
正确处理带有空格的文件名。该-i
给的说法xargs
让你插入在需要的文件名cat
的命令行。括号被替换为cat
从中传递到命令的文件名find
。
这将以递归方式仅打印文件的名称和内容。
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 {} \;
find -name '*.foo' -print
对我非常