Corrigir a codificação de caracteres no PowerShell

Seu script grava ç ou ? no lugar de ç, ou o console mostra texto estranho? O Windows PowerShell 5.1 usa uma codificação diferente conforme o comando. Aqui estão as causas e os parâmetros certos; arquivos já quebrados você repara acima, no navegador.

Funciona com texto e com estes arquivos:

  • CSV
  • TXT
  • JSON
  • XML
  • SRT
  • VTT
  • SMI
  • TSV
  • MD
  • HTML
  • SQL
  • LOG

Por exemplo exportações do Excel, backups de bancos de dados, legendas ou código de sites.

Corrigir

  1. Solte um arquivo ou cole o texto
  2. A correção é automática
  3. Copie ou baixe
ou simplesmente arraste um arquivo para cá

O problema de fundo: cada comando, uma codificação

No Windows PowerShell 5.1, quase todo comando tem sua própria codificação padrão: Get-Content lê arquivos sem BOM como ANSI (Windows-1252), Out-File e > gravam UTF-16, Set-Content grava ANSI e Export-Csv grava ASCII. O PowerShell 7 unificou isso e usa UTF-8 sem BOM em tudo.

Um arquivo UTF-8 lido com Get-Content no PowerShell 5.1

Antes

Usuário;Departamento;Filial
João Conceição;Vendas;São Paulo
Ângela Pereira;Compras;Maceió

Depois

Usuário;Departamento;Filial
João Conceição;Vendas;São Paulo
Ângela Pereira;Compras;Maceió

Ler e gravar arquivos do jeito certo

  • Get-Content dados.csv -Encoding UTF8 lê corretamente arquivos UTF-8, mesmo sem BOM.
  • Set-Content, Out-File e Add-Content gravam UTF-8 com -Encoding UTF8; na 5.1 sempre com BOM.
  • Export-Csv dados.csv -Encoding UTF8 -NoTypeInformation em vez do ASCII padrão, que troca letras acentuadas por ?.
  • Para todos os comandos de uma vez: $PSDefaultParameterValues['*:Encoding'] = 'utf8' no início do script.

Requisições web com Invoke-RestMethod e Invoke-WebRequest

Se um servidor não informa o charset no Content-Type, o Windows PowerShell 5.1 decodifica a resposta como ISO-8859-1. Respostas UTF-8 passam a conter ç. A solução: pegue a resposta como bytes e decodifique você mesmo, por exemplo com [Text.Encoding]::UTF8.GetString((Invoke-WebRequest $url).RawContentStream.ToArray()).

Scripts com caracteres especiais

Se você salva um script como UTF-8 sem BOM, o Windows PowerShell 5.1 o lê como ANSI. Caracteres em textos como Write-Host "Ação" aparecem então como Ação. Salve os .ps1 como UTF-8 com BOM: no VS Code, pela codificação na barra de status; no Notepad++, no menu de codificação com a opção UTF-8-BOM.

O console

Se só a janela do console mostra caracteres estranhos como ├º no lugar de ç, o arquivo geralmente está certo: o console lê UTF-8 como página de código DOS 437 (mais sobre esse padrão). Troque a saída com [Console]::OutputEncoding = [Text.Encoding]::UTF8. Para o que você envia a programas externos, defina também $OutputEncoding = [Text.Encoding]::UTF8.

Se o arquivo já foi gravado quebrado, solte-o na caixa acima: o Mojibuster repara ç e companhia e converte arquivos ANSI para UTF-8. Se o arquivo já contém pontos de interrogação, o texto se perdeu; veja interrogação no lugar de acentos.

Perguntas frequentes

Qual versão do PowerShell eu tenho?

$PSVersionTable.PSVersion mostra. A 5.1 é o Windows PowerShell que vem no Windows; a partir da 7 chama-se só PowerShell e usa UTF-8 por padrão.

Por que o Excel abre errado meu CSV gerado no PowerShell?

O PowerShell 7 grava UTF-8 sem BOM, que o Excel não reconhece. Use -Encoding utf8BOM ou salve o arquivo com BOM no Mojibuster. Mais sobre Excel com acentos errados.

Preciso de chcp 65001?

Só para programas que seguem a página de código do console. Dentro do PowerShell, [Console]::OutputEncoding basta.

Mais guias