如何将多个文件的内容追加到一个文件中

223

我想将五个文件的内容原封不动地复制到一个文件中。我尝试使用cp命令对每个文件进行复制,但这会覆盖之前复制的文件内容。我也尝试过

paste -d "\n" 1.txt 0.txt

但它没有起作用。

我希望我的脚本在每个文本文件的末尾添加换行符。

例如,将1.txt、2.txt、3.txt的内容放入0.txt中。

我该怎么做?


这里有另一个答案:https://dev59.com/YHE85IYBdhLWcg3w2Hfs - Nikos C.
12个回答

385
你需要使用cat命令(缩写为concatenate),并通过shell重定向(>)输出到你的输出文件中。
cat 1.txt 2.txt 3.txt > 0.txt

11
应该是对的吗?为什么我的0.txt文件中所有文本前都有一个换行符? - Steam
2
你想保留 0.txt 的内容吗? - sehe
18
@blasto 这取决于情况。使用>>来将一个文件的内容追加到另一个文件中,而使用>则会用指定的内容覆盖输出文件。至于换行符,文件1.txt中是否有作为第一个字符的换行符?您可以使用od -c命令来查找,并检查第一个字符是否为\n - radical7
2
@blasto 你肯定朝着正确的方向前进了。Bash确实接受{...}形式进行文件名匹配,所以也许引号在你的脚本中有些问题?我总是尝试在shell中使用ls来处理这样的事情。当我把命令搞对了,我就直接将其复制粘贴到脚本中。你可能还会发现在你的脚本中使用-x选项很有用——它会在执行之前回显脚本中的扩展命令。 - radical7
2
为了防止别人犯同样的错误:cat 1.txt 2.txt > 1.txt 只会用 2.txt 的内容覆盖 1.txt,而不是将两个文件合并到第一个文件中。 - Rico Ocepek
显示剩余4条评论

120

对于那些像我一样仍然偶然发现这篇文章的人,另一个选项是使用find -exec

find . -type f -name '*.txt' -exec cat {} + >> output.file

在我的情况下,我需要一个更强大的选项,它可以查找多个子目录,因此我选择使用 find。拆分一下:

find .

查找当前工作目录。

-type f

只对文件感兴趣,不包括目录等。

-name '*.txt'

通过名称缩小结果集

-exec cat {} +

对于每个结果执行cat命令。"+"表示只生成一个cat实例(感谢@gniourf_gniourf)

 >> output.file

如其他答案所述,将连接的内容附加到输出文件的末尾。


11
这个答案有很多缺陷。首先,通配符*.txt必须加引号(否则,整个find命令将毫无用处)。另一个缺陷来自于一个严重的误解:执行的命令并不是cat >> 0.txt {},而是cat {}。实际上,你的命令等同于{ find . -type f -name *.txt -exec cat '{}' \; ; } >> 0.txt(我添加了分组让你意识到实际发生了什么)。另一个缺陷是find会查找文件0.txt,而cat会抱怨说“输入文件是输出文件”。 - gniourf_gniourf
谢谢您的更正。我的情况有些不同,我没有考虑到一些可能适用于这种情况的问题。 - mopo922
你应该在命令的结尾处加上 >> output.file,这样就不会让任何人(包括你自己)误以为 find 会为每个找到的文件执行 cat {} >> output.file - gniourf_gniourf
3
很好的回答和警告词 - 我修改了我的命令为:find . -type f -exec cat {} + >> outputfile.txt,但是我不知道为什么我的输出文件会不停增长到数十个G,尽管目录只有50兆。这是因为我一直在将outputfile.txt追加到它自己上面!所以请确保正确命名该文件或将其放置在完全不同的目录中,以避免这种情况。 - Thisisstackoverflow
我认为一个更简单的命令是:(find . -type f -name "f*.log*" |xargs cat) > result.log - KIR
显示剩余3条评论

51

如果您有特定的输出类型,则可以执行以下操作

cat /path/to/files/*.txt >> finalout.txt

6
请记住,虽然您可以使用此方法合并文件,但可能会失去维护合并顺序的可能性。如果您的文件命名为 file_1file_2、……、file_11,那么这可能会影响到您,因为文件排序的自然顺序会导致问题。 - Mike Doe

22

如果您的所有文件命名方式相似,您可以简单地执行以下操作:

cat *.log >> output.log

19

如果您所有的文件都在一个目录中,您可以简单地执行以下操作:

cat * > 0.txt

文件1.txt、2.txt等将会合并到0.txt中。


已经由Eswar回答了。请记住,您正在失去维护合并顺序的可能性。如果您的文件命名为file_1file_2,... file_11,那么这可能会影响您,因为文件排序的自然顺序。 - Mike Doe

17
for i in {1..3}; do cat "$i.txt" >> 0.txt; done

我发现这个页面,是因为我需要将952个文件合并成一个文件。如果你有很多文件,我发现这种方法更有效。它会循环执行你需要的任意次数,并使用“>>”来将每个文件附加到0.txt的末尾。

编辑:

正如评论中提到的:

cat {1..3}.txt >> 0.txt
或者。
cat {0..3}.txt >> all.txt

1
你可以在Bash中使用大括号扩展写作cat {1,2,3}.txt >> 0.txt。 - mcheema

6

如果您的文件包含标题,并且您想在输出文件中将它们删除,可以使用以下方法:

for f in `ls *.txt`; do sed '2,$!d' $f >> 0.out; done

6

另一个选项是 sed

sed r 1.txt 2.txt 3.txt > merge.txt 

或者...
sed h 1.txt 2.txt 3.txt > merge.txt 

或者...

sed -n p 1.txt 2.txt 3.txt > merge.txt # -n is mandatory here

或者不使用重定向...

sed wmerge.txt 1.txt 2.txt 3.txt

请注意,最后一行也要写 merge.txt(而不是 wmerge.txt!)。您可以使用 w"merge.txt" 来避免与文件名混淆,并使用 -n 进行静默输出。
当然,您也可以使用通配符缩短文件列表。例如,在上面的示例中,如果有编号的文件,您可以使用大括号指定范围,如下所示:
sed -n w"merge.txt" {1..3}.txt

4
将所有文本文件合并成一个。
find . | xargs cat > outfile

xargs将find .的输出行作为cat的参数。

find有许多选项,例如-name '*.txt'或-type。

如果您想在管道中使用它,应该检查它们。


你应该解释一下你的命令是干什么的。顺便说一下,你应该使用带有--print0的find和带有-0的xargs,以避免一些特殊文件名的注意事项。 - Orsiris de Jong

3
如果原始文件包含不可打印字符,使用cat命令时它们将丢失。使用'cat -v',非可打印字符将转换为可见字符字符串,但输出文件仍不包含原始文件中的实际非可打印字符。对于少量文件,另一种选择可能是在处理非打印字符的编辑器(例如vim)中打开第一个文件。然后移动到文件底部并输入“:r second_file_name”。这将拉入第二个文件,包括非打印字符。可以为其他文件执行相同操作。当所有文件都被读入后,输入“:w”。最终结果是第一个文件现在包含了它最初的内容以及读入文件的内容。

这不太适合脚本化。 - FKEinternet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接