虽然Powershell几乎不可能实现,但我想要实现的目标却相当简单。
我想显示文件的完整路径,其中一些文件的名称中包含阿拉伯语,中文,日语和俄语字符
在控制台中看到的输出正在被另一个脚本消耗。输出包含?而不是实际的人物。
执行的命令是
(Get-ChildItem -Recurse -Path "D:\test" -Include *unicode* | Get-ChildItem -Recurse).FullName
是否有任何简单的方法来启动PowerShell(通过命令行或以任何方式写入脚本),以便正确地看到输出。
附:我在Stack Overflow上经历了许多类似的问题,但除了称之为Windows控制台子系统问题之外,没有其他任何输入。
请注意,类似Unix的平台上的PowerShell Core终端窗口默认情况下是UTF-8感知的(通常,现在,鉴于现代类Unix平台使用基于UTF-8的语言环境)。 在Windows上,从PowerShell Core 6.2.0开始还不是这样,但应尽快实现 - 请参阅this GitHub issue
使您的Windows PowerShell控制台窗口符合Unicode(UTF-8):
SimSun-ExtB
,仅适用于Windows 10。
有关Windows字体针对哪些脚本(字母)的列表,请参阅Wikipedia。
要更改字体,请单击窗口左上角的图标并选择Properties
,然后切换到Fonts
选项卡并选择感兴趣的TrueType字体。
有关如何提供其他字体的信息,请参阅this SU answer的not2quibit。65001
,即UTF-8代码页(通常使用chcp 65001
完成,但下面的PowerShell命令会隐式执行)。
必须指示PowerShell使用UTF-8与外部实用程序通信,无论是在向外部程序发送输入还是从外部程序接收输出时。Windows PowerShell中的以下魔术咒语就是这样做的(如上所述,这隐式执行chcp 65001
):
$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding =
New-Object System.Text.UTF8Encoding
要保留这些设置,即默认情况下将您的未来交互式PowerShell会话设置为UTF-8,请将上面的命令添加到$PROFILE
文件中。
重要:
find.exe
和findstr.exe
,已在Windows 10中修复。
请参阅本文的底部,了解如何根据需要临时切换到UTF-8来绕过此问题,以便调用给定的实用程序。对eryksun的所有投入的帽子的提示。
?
,表示当前字体缺乏支持,但您可以在不丢失信息的情况下将这些字符复制并粘贴到其他位置,正如eryksun所观察到的那样。65001
,PowerShell也能够将Unicode字符输出到控制台。
但是,这本身并不能保证其他程序能够正确处理这样的输出 - 见下文。$OutputEncoding
首选项变量中指定的字符编码,在Windows PowerShell中默认为ASCII(!),这意味着任何非ASCII字符都被音译为文字?
字符,导致信息丢失。 (相比之下,值得称道的是,PowerShell Core现在使用(无BOM)UTF-8作为默认编码,无处不在。)
相比之下,将非ASCII参数(而不是stdout(管道)输出)传递给外部程序似乎不需要特殊配置(我不清楚为什么这样做);例如,即使使用默认配置,以下Node.js命令也会正确返回€: 1
:
node -pe "process.argv[1] + ': ' + process.argv[1].length" €
[Console]::OutputEncoding
:
控制在控制台将程序输出转换为控制台显示字符时控制的字符编码。
还告诉PowerShell从外部程序捕获输出时要采用的编码方式。
结果是,如果你需要从产生UTF-8的程序中捕获输出,你需要将[Console]::OutputEncoding
设置为UTF-8;设置$OutputEncoding
只涵盖输入(到外部程序)方面。[Console]::InputEncoding
将键盘输入的编码设置到控制台中。# Save the current settings and temporarily switch to UTF-8.
$oldOutputEncoding = $OutputEncoding; $oldConsoleEncoding = [Console]::OutputEncoding
$OutputEncoding = [Console]::OutputEncoding = New-Object System.Text.Utf8Encoding
# Call the UTF-8 program, using Node.js as an example.
# This should echo '€' (`U+20AC`) as-is and report the length as *1*.
$captured = '€' | node -pe "require('fs').readFileSync(0).toString().trim()"
$captured; $captured.Length
# Restore the previous settings.
$OutputEncoding = $oldOutputEncoding; [Console]::OutputEncoding = $oldConsoleEncoding
chcp
的有效65001
值打破了某些外部程序的控制台输出甚至是旧版Windows中的批处理文件,最终可能源于WriteFile()
Windows API函数中的错误(也被标准C库使用),如65001
中所讨论的那样,错误地报告了代码页this blog post生效的字符数而不是字节数。
根据bobince对2008年this answer的评论,由此产生的症状是:“我的理解是返回字节数的调用(例如fread / fwrite / etc)实际上返回了一些字符数。导致各种各样的症状,例如输入读数不完整,fflush挂起,批处理文件损坏等。“阐述了Alexander Martin's answer。出于测试目的,我使用来自不同Unicode子范围的valid names创建了一些文件夹和文件,如下所示:
例如,使用Courier New控制台字体,在PowerShell控制台中显示替换符号而不是CJK字符:
另一方面,使用SimSun控制台字体,(显示不太清楚)替换符号显示而不是阿拉伯语和希伯来语字符,而CJK字符似乎显示正确:
请注意,仅显示所有替换符号,而保留真实字符,如下面的PowerShell控制台上的“复制和粘贴”中所示:
PS D:\PShell> (Get-ChildItem 'D:\bat\UnASCII Names\' -Dir).Name
Arabic (عَرَبِيّ)
CJK (中文(繁體))
Czech (Čeština)
Greek (Γρεεκ)
Hebrew (עִבְרִית)
Japanese (日本語)
MathBoldScript (𝓜𝓪𝓽𝓱𝓑𝓸𝓵𝓭𝓢𝓬𝓻𝓲𝓹𝓽)
Russian (русский язык)
Türkçe (Türkiye)
‹angles›
☺☻♥♦
为了完整起见,这里是适用于Enable More Fonts for the Windows Command Prompt的注册表值(这适用于Windows PowerShell控制台):
(Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Console\TrueTypeFont' |
Select-Object -Property [0-9]* | Out-String).Split(
[System.Environment]::NewLine,
[System.StringSplitOptions]::RemoveEmptyEntries) |
Sort-Object
样本输出:
0 : Consolas
00 : Source Code Pro
000 : DejaVu Sans Mono
0000 : Courier New
00000 : Simplified Arabic Fixed
000000 : Unifont
0000000 : Lucida Console
932 : *MS ゴシック
936 : *新宋体
确保您的字体包含已安装的所有有问题的字符并设置为Win32控制台字体。如果我没记错,请单击窗口左上角的PowerShell图标,然后选择“属性”。生成的弹出对话框应该有一个选项来设置使用的字体。它可能必须是位图(.FON
或.FNT
)字体。