将多个文件复制(附加)到单个目标文件 [英] Copy (append) multiple files into a single destination file
问题描述
我在使用PowerShell将多个CSV文件合并为一个文件时遇到了奇怪的问题。我在windows7的cmd提示符中已经做过很多次了,但这里的输出只包含最早的文件。该命令是标准内容:
C:> copy *.csv output.csv
正如我所说,我得到的只是复制到这个新文件中的最早的CSV,其他什么都没有。这是PowerShell与简单命令提示符的问题吗?
谢谢 迈克尔
推荐答案
如lit在注释中指出的,在PowerShell中copy
是Copy-Item
cmdlet的内置别名,其功能与cmd.exe
的内部copy
命令不同:
从PowerShell 7.2.1开始,
Copy-Item
不支持将多个文件合并为单个目标文件。有关-潜在内容修改-Get-Content
解决方案,请参阅底部部分。目前,如果
Copy-Item
的-Destination
参数(第二个位置参数,在您的情况下为output.csv
)是文件,则所有-Path
参数(第一个位置参数,在您的情况下为*.csv
)都被顺序复制到相同的目标文件-换句话说:匹配通配符模式*.csv
的最后文件,output.csv
只是的副本-有关讨论,请参阅GitHub issue #12805。
要使用cmd.exe
的copy
命令,合并输入文件形成目标文件,通过cmd /c
调用:
cmd /c 'copy /y /b *.csv output.csv'
警告:正如aschipfl's helpful answer中所讨论的,如何处理先前存在的output.csv
文件取决于output.csv
是否恰好是通配符模式*.csv
匹配的第一个文件。请使用此处建议的解决方法,或者只需确保事先不存在output.csv
文件。
请注意添加了:
/y
,如果目标文件已存在则不显示确认提示/b
,以二进制模式复制,这将防止将Substitute character、0x1a
(您可以使用Ctrl-Z交互生成的Substitute character、0x1a
)字符追加到目标文件。
顺便提一下:在类Unix平台上,您可以使用sh -c 'cat *.csv > output.csv'
,但在那里,始终必须首先确保没有预先存在的output.csv
文件,因为这会导致文件不断增长。
或者,您可以使用Get-Content
cmdlet合并多个文本文件,如LIT所建议并由zett42在有关问题的评论中改进,但这样做可能会更改字符编码和换行格式,在给定用例中可能需要也可能不需要:
# !! Caveat: may change character encoding and newline format.
# !! -Encoding utf8 used as an example.
Get-Content *.csv -Exclude output.csv | Set-Content -Encoding utf8 output.csv
Get-Content
,假定它正确解释文本文件的编码(如果存在,则基于文件的BOM,否则假定为默认),将文件的行加载到.NET字符串中,并且不保留有关文件字符编码的信息。类似地,编写cmdlet的文件
Out-File
(及其有效别名>
)和Set-Content
对.NET输入字符串进行操作,并在保存到文件时使用默认编码-尽管可能会通过-Encoding
参数请求不同的编码。换句话说:如果您的输入文件具有要在目标文件中保留的一致的非默认编码,您(A)需要知道该编码是什么,并(B)通过
-Encoding
请求使用该编码。注意:Windows PowerShell对于
Get-Content
和Set-Content
默认为系统的旧ANSI代码页,对于Out-File
/>
默认为UTF-16LE(";Unicode";)。相比之下,PowerShell(Core)7+现在很好地使用(无BOM)UTF-8,在所有cmdlet中保持一致。
此外,由于默认情况下由
Get-Content
逐行读取文件,有关特定换行格式的信息将丢失。然后,保存文件的cmdlet使用平台本机换行符序列(在Windows上为CRLF("`r`n"
),在类Unix平台上为LF("`n"
)),因此目标文件可能以不同的换行行格式结束。此外,有关给定文件是否有尾随换行符的信息也会丢失。您可以通过将
Get-Content -Raw
与Set-Content -NoNewLine
合并来保留原始换行格式和尾随换行符状态,而不必将每个文件全部读取到内存中(文本文件通常不存在问题):Get-Content -Raw *.csv -Exclude output.csv | Set-Content -Encoding utf8 -NoNewLine output.csv
至于用例:
您可以在以下一个或多个场景中使用
Get-Content
+Set-Content
:如果您的输入文件是使用变化字符编码(所有
Get-Content
都需要能够识别)的文本文件,以便创建一致编码的目标文件。同样,即使输入文件具有相同的编码,您也可以选择转码内容,即为目标文件选择不同的编码。
如果要将换行符格式规范化为平台本机格式,并且可能还要确保存在尾随换行符。
否则,如果必须按原样保留输入文件的内容--尤其是对于二进制文件--请使用
cmd /c 'copy ...'
方法。- 要在PowerShell中解决此问题,需要使用较低级别的.NET API。
这篇关于将多个文件复制(附加)到单个目标文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!