我在 StackOverflow 上发现了以下问题的两个看似矛盾的答案:
第一个问题的最佳答案表明:
find . -name *.txt -print0 | xargs -0 cat >> out.txt
而第二个问题的最佳答案表明:
find . -name *.txt -print0 | xargs -0 cat > out.txt
据我所知,第一个是正确的,因为它使用了>>
(追加)运算符,但第二个不是,因为它使用了>
我认为只是将输出重定向到文件的运算符。然而,第二个答案有更多票数(10),也被接受,没有评论。两个答案都正确吗?为什么?那么拥有这两个运营商的目的是什么呢?
答案1
第二个例子:
find . -name '*.txt' -print0 | xargs -0 cat > out.txt
完全合法,out.txt
每次运行时都会重新创建该文件,而第一个文件out.txt
运行时将连接到。但这两个命令本质上做的是相同的事情。
令人困惑的是这个问题xargs -0 cat
。人们认为重定向到out.txt
是该命令的一部分,但事实并非如此。重定向是在xargs -o cat
通过 STDIN 接收输入之后发生的,然后将该输出作为单个流输出到 STDOUT。这xargs
是优化文件的目录而不是它们的输出。
这是一个展示我所说内容的例子。如果我们在和 文件输出pv -l
之间插入一个,我们可以看到 cat 写入了多少行。xargs -0 cat
out.txt
例子
为了展示这一点,我创建了一个包含 10,000 个文件的目录。
for i in `seq -w 1 10000`;do echo "contents of file$i.txt" > file$i.txt;done
每个文件看起来都类似于:
$ more file00001.txt
contents of file00001.txt
输出pv
:
$ find . -name '*.txt' -print0 | xargs -0 cat | pv -l > singlefile.rpt
10k 0:00:00 [31.1k/s] [ <=>
singlefile.rpt
正如我们所看到的,我的文件中写入了 10k 行。如果xargs
向我们传递输出块,那么我们会看到呈现给 的行数减少pv
。
答案2
那么拥有这两个运营商的目的是什么呢?
这很简单:因为有不同的用例。有时首先将目标文件截断为大小 0 很有用,有时(例如日志文件)将数据附加到文件更有意义。
在这种情况下,追加是没有意义的。您想要一个与您选择的文件内容完全相同的文件,而不是“一个开头有任何数据、结尾有所选文件内容的文件”。
答案3
我会选择第二个。当你按回车键时,stdout 的重定向会被 bash 捕获,所以这不像你为 find/xargs 的每一行创建一个新的重定向(这可能是他们的想法)。如果out.txt
不存在,它们应该是相同的,如果已经有数据,那么第二个至少将文件重置为已知内容(即没有内容)。