连接数千个文件:> vs >>

连接数千个文件:> vs >>

我在 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 catout.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不存在,它们应该是相同的,如果已经有数据,那么第二个至少将文件重置为已知内容(即没有内容)。

相关内容