为什么Powershell重定向>>会更改文本内容的格式?

roc*_*ain 3 powershell io-redirection

我想使用重定向附加>>或写入>来写入txt文件,但是当我这样做时,我收到了奇怪的格式“ \ x00a \ x00p ...”

我成功使用了set-content和add-content,为什么它们按预期运行,但>>和>重定向运算符却没有运行?

使用Powershell'cat'以及简单的python打印显示输出。

rocket_brain> new-item test.txt
rocket_brain> "appended using add-content" | add-content test.txt
rocket_brain> cat test.txt

 appended using add-content
Run Code Online (Sandbox Code Playgroud)

但是如果我使用重定向附加>>

rocket_brain> "appended using redirect" >> test.txt
rocket_brain> cat test.txt

 appended using add-content
 a p p e n d e d   u s i n g   r e d i r e c t

Run Code Online (Sandbox Code Playgroud)

简单的python脚本:read_test.py

with open("test.txt", "r") as file:   # open test.txt in readmode
    data = file.readlines()           # append each line to the list data
    print(data)                       # output list with each input line as an item
Run Code Online (Sandbox Code Playgroud)

使用read_test.py我看到格式上的差异

rocket_brain> python read_test.txt
 ['appended using add-content\n', 'a\x00p\x00p\x00e\x00n\x00d\x00e\x00d\x00 \x00u\x00s\x00i\x00n\x00g\x00 \x00r\x00e\x00d\x00i\x00r\x00e\x00c\x00t\x00\r\x00\n', '\x00']
Run Code Online (Sandbox Code Playgroud)

注意:如果我只使用重定向附加>>(或写>)而没有先使用add-content,则cat输出看起来很正常(而不是隔开),但是当我使用时,行的/ x00p格式python脚本(包括以>运算符开头的所有add-content命令)。在记事本(或VS等)中打开文件,文本始终看起来像预期的那样。在cmd(而不是PS)中使用>>或>也会以预期的ascii格式存储文本。

相关链接cmd重定向运算符PS重定向运算符

mkl*_*nt0 6

注意:问题最终是在Windows PowerShell中,不同的cmdlet /运算符使用不同的默认编码。此问题已在PowerShell Core中得到解决,该内核始终使用无BOM的UTF-8。


  • >>盲目地适用Out-File的默认编码附加时到现有文件(实际上,>象的行为Out-File>>Out-File -Append),其在Windows PowerShell中是命名的编码Unicode,即UTF-16LE,其中大多数字符被编码为2字节序列,甚至是那些在ASCII范围内;后者的高字节为0x0NUL)。

    • 因此,除非目标文件的现有内容使用相同的编码否则最终将混合使用不同的编码,这就是您所遇到的情况。[1]
  • Add-Content相比之下,虽然确实尝试检测文件的现有编码再次感谢js2010,则将其用于一个文件,在这种情况Set-Content下,将应用默认编码,在Windows PowerShell中该编码为named Default,它表示系统的活动ANSI代码页

    • 因此,为了匹配Add-Content在添加更多内容时您的调用最初创建的单字节ANSI编码,请 使用Out-File -Append -Encoding Default代替>>,或简单地继续使用Add-Content

      • 或者,Add-Content -Encoding ...Out-File -Append 呼叫中选择其他编码并与之匹配;UTF-8通常是最佳选择,不过请注意,当您在Windows PowerShell中创建UTF-8文件时,它将以BOM表(将文件标识为UTF-8的伪字节顺序标记)开头,类似于Unix平台通常不期望)。

      • 在PowerShell v5.1 +中,您还可以全局更改默认编码,包括for >>>(在早期版本中是不可能的)。例如,要更改为UTF-8,请使用:
        $PSDefaultParameterValues['*:Encoding']='UTF8'


除了不同的默认编码(在Windows PowerShell中)外,重要的是要注意Set-Content/ Add-Content一方面和>/ >>/ Out-File [-Append]的行为与非字符串输入有根本不同

简而言之:前者将简单.ToString()格式应用于输入对象,而后者执行与控制台中相同的输出格式- 有关详细信息,请参见此答案


[1]由于设置的初始内容Add-Content,Windows PowerShell将文件解释为ANSI编码(没有BOM时的默认设置),其中每个字节都是其自己的字符。因此,后面附加的UTF-16内容也将被解释为ANSI,因此0x0字节本身就被当作字符对待,并像空格一样打印到控制台。