使用PowerShell连接文件

37

我正在使用PowerShell 3。

如何最佳地将文件连接在一起?

file1.txt + file2.txt = file3.txt

PowerShell提供直接执行此操作的功能吗?还是需要将每个文件的内容加载到本地变量中?


可能是如何在PowerShell中连接两个文本文件?的重复问题。 - phuclv
9个回答

54
如果所有文件都存在于同一目录中,并且可以通过简单的模式匹配找到,请使用以下代码将所有文件合并为一个。
Get-Content .\File?.txt | Out-File .\Combined.txt

1
“Get-Content ... | Out-File ...” 可能是表达 我的 意图最清晰的方式,当我像这样做某事时。对我来说,是否能匹配简单模式并不重要;在 PowerShell 中选择文件的方法有很多种。Out-File 的默认编码对我来说比 Set-Content 的默认编码更常正确;Out-File 默认为 Unicode,而 Set-Content 默认为 ASCII。 - Mike Sherrill 'Cat Recall'
4
对于所有想知道为什么在Windows 8+上失败的人,请使用以下命令:Get-Content .\*.txt | Out-File .\Combined.txt - omni
1
就像@masi所说,我被模式表达式搞糊涂了。对于像我这样密集的人来说,问号(?)只匹配一个字符。如果您需要匹配多个字符,请使用星号(*)。 - Jason
9
对我来说,这产生了一个递归的文件炸弹,请不要将输出文件放在与输入文件相同的目录中。 - Lennart
不是很有用,因为它没有显示输入文件必须用逗号分隔。 - Pedro Machado
输出文件将使用UTF-16编码,这会使文件大小增加一倍。 - anotherfred

33

我会选择这条路线:

Get-Content file1.txt, file2.txt | Set-Content file3.txt

如果您需要使用Set-Content输出非ASCII文本,则需要在Set-Content命令中使用-Encoding参数,因为ASCII是Set-Content的默认编码。


+1,我总是喜欢这些简单的 :) 当然,Out-File 也同样好。 - Austin T French
@AthomSfere 是的,如果你想要 Unicode 编码,Out-File 默认会使用它。 - Keith Hill
这个答案避免了在使用*.txt作为输入时出现递归问题(因为set-content锁定了文件)。 - Peter Wishart

8
如果您需要更多的灵活性,您可以使用类似于这样的东西。
Get-ChildItem -Recurse *.cs | ForEach-Object { Get-Content $_ } | Out-File -Path .\all.txt

7

警告: 使用简单的 Get-Content 进行串联(无论是否使用 -Raw 标志)仅适用于文本文件;Powershell 对此太过“热心”了:

  • 如果不使用-Raw,它会“修复”(也就是打破,断开)换行符,或者Powershell认为是换行符的地方。
  • 使用 -Raw,你会在每个文件部分的结尾处得到一个终止行结束符(通常是CR+LF),它会添加到管道的末尾。新版 Powershell 的 Set-Content 中有一个选项可用于此。

要串联二进制文件(即任意被拆分并需要重新组合的文件),请使用以下方法之一:

Get-Content -Raw file1, file2 | Set-Content -NoNewline destination

或者像这样:

Get-Content file1 -Encoding Byte -Raw | Set-Content destination -Encoding Byte
Get-Content file2 -Encoding Byte -Raw | Add-Content destination -Encoding Byte

另一种选择是使用CMD shell并使用

copy file1 /b + file2 /b + file3 /b + ... destinationfile

您不得覆盖任何部分,也就是说,不能使用其中任何一个部分作为目标。目标文件必须与任何部分都不相同。否则,您将会遭遇意外情况,并且必须找到文件部分的备份。


在PowerShell 5上,尝试将几个2GB的文件合并时失败了。但是CMD复制效果很好! - Carl Walsh

1
gc file1.txt, file2.txt > output.txt

我认为这已经是最短的了。


你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

1

如果您想确保连接按特定顺序完成,请使用Sort-Object -Property <Some Name>参数。例如,根据名称升序排序进行连接:

Get-ChildItem -Path ./* -Include *.txt -Exclude output.txt | Sort-Object -Property Name | ForEach-Object { Get-Content $_ } | Out-File output.txt

重要提示:-ExcludeOut-File必须包含相同的值,否则它将递归地继续添加到output.txt,直到您的磁盘已满。

请注意,因为您正在使用-Include,所以-Path参数末尾必须附加*,如Get-ChildItem文档中所述。


0
基于 @Keith 的回答,以下是一个概括:
使用以下命令进行筛选:gc <some regex expression> | sc output

2
虽然这个答案看起来像是针对bash的,但短名称的原因是PowerShell中的别名 - 其中gc是Get-Content,而sc是Set-Content。 - c69

0

这是一个有趣的示例,展示如何基于 Powershell 7 创建一个包含压缩文件的图像文件。

Get-Content -AsByteStream file1.png, file2.7z | Set-Content -AsByteStream file3.png
Get-Content -AsByteStream file1.png, file2.7z | Add-Content -AsByteStream file3.png

0

以上的例子对我来说都不太好用,因为我处理的是大文件(5GB+)。Set-Content 首先会将所有内容加载到内存中(导致内存爆炸),然后再写入。相反,使用文本流写入更好。在查看了这个其他���题的答案后,我采用了下面的方法来合并一个头文件和一个数据文件!

$file = [system.io.file]::OpenWrite("$($pwd.Path)\out.txt")
$writer = New-Object System.IO.StreamWriter($file)

cat headers.txt,data.txt | ForEach-Object { $writer.WriteLine($_) }

$writer.Close()
$file.Close()

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