Modification de l'encodage de sortie par défaut de PowerShell en UTF-8

105

Par défaut, lorsque vous redirigez la sortie d'une commande vers un fichier ou que vous la dirigez vers quelque chose d'autre dans PowerShell, l'encodage est UTF-16, ce qui n'est pas utile. Je cherche à le changer en UTF-8.

Cela peut être fait au cas par cas en remplaçant la >foo.txtsyntaxe par | out-file foo.txt -encoding utf8mais c'est gênant de devoir répéter à chaque fois.

La manière persistante de définir les éléments dans PowerShell est de les insérer \Users\me\Documents\WindowsPowerShell\profile.ps1; J'ai vérifié que ce fichier est bien exécuté au démarrage.

Il a été dit que l'encodage de sortie peut être réglé avec $PSDefaultParameterValues = @{'Out-File:Encoding' = 'utf8'}mais j'ai essayé cela et cela n'a eu aucun effet.

https://blogs.msdn.microsoft.com/powershell/2006/12/11/outputencoding-to-the-rescue/ qui parle d' $OutputEncodingapparence à première vue comme si cela devrait être pertinent, mais ensuite il parle de la sortie en cours de codage en ASCII, ce qui n'est pas ce qui se passe réellement.

Comment configurer PowerShell pour utiliser UTF-8?

rwallace
la source

Réponses:

162

Remarque: ce qui suit s'applique à Windows PowerShell .
Consultez la section suivante pour l' édition multiplateforme PowerShell Core (v6 +) .

  • Sur PSv5.1 ou supérieur , où >et >>sont effectivement des alias de Out-File, vous pouvez définir l'encodage par défaut pour >/ >>/ Out-Filevia la $PSDefaultParameterValuesvariable de préférence :

    • $PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
  • Sur PSv5.0 ou au- dessous , vous ne pouvez pas modifier le codage >/>> , mais, sur PSV3 ou plus , la technique ci - dessus ne travail pour les appels explicites àOut-File .
    (La $PSDefaultParameterValuesvariable de préférence a été introduite dans PSv3.0).

  • Sur PSv3.0 ou version ultérieure , si vous souhaitez définir le codage par défaut pour toutes les applets de commande qui prennent
    en charge un -Encodingparamètre
    (qui dans PSv5.1 + inclut >et >>), utilisez:

    • $PSDefaultParameterValues['*:Encoding'] = 'utf8'

Si vous placez cette commande dans vos$PROFILE applets de commande, telles que Out-FileetSet-Content utilisera le codage UTF-8 par défaut, mais notez que cela en fait un paramètre global de session qui affectera toutes les commandes / scripts qui ne spécifient pas explicitement un codage.

De même, assurez-vous d'inclure dans vos scripts ou modules de telles commandes que vous souhaitez se comporter de la même manière , afin qu'elles se comportent effectivement de la même manière même lorsqu'elles sont exécutées par un autre utilisateur ou une machine différente.

Attention : ** PowerShell, à partir de la v5.1, crée invariablement des fichiers UTF-8 _ avec une (pseudo) nomenclature _ ** , ce qui n'est habituel que dans le monde Windows - les utilitaires Unix ne reconnaissent pas cette nomenclature (voir en bas); voir cet article pour des solutions de contournement qui créent des fichiers UTF-8 sans nomenclature.

Pour obtenir un résumé du comportement de codage de caractères par défaut extrêmement incohérent dans de nombreuses applets de commande standard Windows PowerShell , consultez la section inférieure.


La $OutputEncodingvariable automatique n'est pas liée et s'applique uniquement à la façon dont PowerShell communique avec les programmes externes (quel encodage PowerShell utilise lors de l'envoi de chaînes) - elle n'a rien à voir avec l'encodage que les opérateurs de redirection de sortie et les applets de commande PowerShell utilisent pour enregistrer dans des fichiers.


Lecture facultative: La perspective multiplateforme: PowerShell Core :

PowerShell est désormais multiplateforme , via son édition PowerShell Core , dont l'encodage - judicieusement - est par défaut UTF-8 sans BOM , en ligne avec les plates-formes de type Unix.

  • Cela signifie que les fichiers de code source sans nomenclature sont supposés être UTF-8 et en utilisant >/ Out-File/ Set-Contentpar défaut BOM-less UTF-8; l'utilisation explicite de l' utf8 -Encodingargument crée également un UTF-8 sans nomenclature , mais vous pouvez choisir de créer des fichiers avec la pseudo-nomenclature avec la utf8bomvaleur.

  • Si vous créez des scripts PowerShell avec un éditeur sur une plate-forme de type Unix et de nos jours même sur Windows avec des éditeurs multiplateformes tels que Visual Studio Code et Sublime Text, le *.ps1fichier résultant n'aura généralement pas de pseudo-BOM UTF-8:

    • Cela fonctionne bien sur PowerShell Core .
    • Il peut se casser sous Windows PowerShell , si le fichier contient des caractères non ASCII; si vous devez utiliser des caractères non ASCII dans vos scripts, enregistrez-les au format UTF-8 avec BOM .
      Sans la nomenclature, Windows PowerShell interprète (mis) votre script comme étant encodé dans la page de codes héritée «ANSI» (déterminée par les paramètres régionaux du système pour les applications pré-Unicode; par exemple, Windows-1252 sur les systèmes anglais américain).
  • A l' inverse, les fichiers qui font ont le pseudo-BOM peut être problématique sur Unix plates - formes, car ils provoquent des utilitaires Unix UTF-8 tels que cat, sedet awk- et même certains éditeurs tels que gedit- pour passer le pseudo-BOM à travers , par exemple, pour le traiter comme des données .

    • Cela peut ne pas toujours être un problème, mais peut certainement l'être, comme lorsque vous essayez de lire un fichier dans une chaîne bashavec, par exemple, text=$(cat file)ou text=$(<file)- la variable résultante contiendra le pseudo-BOM comme les 3 premiers octets.

Comportement de codage par défaut incohérent dans Windows PowerShell :

Malheureusement, le codage de caractères par défaut utilisé dans Windows PowerShell est extrêmement incohérent; L' édition multiplateforme PowerShell Core , comme indiqué dans la section précédente, a mis un terme à cela.

Remarque:

  • Ce qui suit n'aspire pas à couvrir toutes les applets de commande standard.

  • Googler les noms des applets de commande pour trouver leurs rubriques d'aide vous montre désormais la version PowerShell Core des rubriques par défaut; utilisez la liste déroulante des versions au-dessus de la liste des rubriques sur la gauche pour passer à une version de Windows PowerShell .

  • Au moment d'écrire ces lignes, la documentation prétend souvent à tort que ASCII est l'encodage par défaut dans Windows PowerShell - consultez ce problème de documentation GitHub .


Cmdlets qui écrivent :

Out-Fileet >/ >>créer "Unicode" - UTF-16LE - des fichiers par défaut - dans lesquels chaque caractère de la plage ASCII (aussi) est représenté par 2 octets - qui diffère notablement de Set-Content/ Add-Content(voir point suivant); New-ModuleManifestet Export-CliXmlcréez également des fichiers UTF-16LE.

Set-Content(et Add-Contentsi le fichier n'existe pas encore / est vide) utilise le codage ANSI (le codage spécifié par la page de codes héritée ANSI des paramètres régionaux du système actif, que PowerShell appelle Default).

Export-Csvcrée en effet des fichiers ASCII, comme documenté, mais voir les notes -Appendci-dessous.

Export-PSSession crée des fichiers UTF-8 avec BOM par défaut.

New-Item -Type File -Value crée actuellement sans nomenclature (!) UTF-8.

La Send-MailMessagerubrique d'aide affirme également que le codage ASCII est la valeur par défaut - je n'ai pas personnellement vérifié cette affirmation.

Start-Transcript crée invariablement des fichiers UTF-8 avec BOM, mais voir les remarques -Appendci-dessous.

Concernant les commandes qui s'ajoutent à un fichier existant:

>>/ Out-File -AppendFaire aucune tentative pour correspondre à l'encodage d'un fichier de contenu existant . Autrement dit, ils appliquent aveuglément leur codage par défaut, sauf indication contraire avec -Encoding, ce qui n'est pas une option avec >>(sauf indirectement dans PSv5.1 +, via $PSDefaultParameterValues, comme indiqué ci-dessus). En bref: vous devez connaître l'encodage du contenu d'un fichier existant et l'ajouter en utilisant ce même encodage.

Add-Contentest l'exception louable: en l'absence d' -Encodingargument explicite , il détecte l'encodage existant et l'applique automatiquement au nouveau contenu. Merci, js2010 . Notez que dans Windows PowerShell, cela signifie que c'est le codage ANSI qui est appliqué si le contenu existant n'a pas de nomenclature, alors qu'il s'agit de UTF-8 dans PowerShell Core.

Cette incohérence entre Out-File -Append/ >>et Add-Content, qui affecte également PowerShell Core , est abordée dans ce problème GitHub .

Export-Csv -Append correspond partiellement à l'encodage existant: il ajoute aveuglément UTF-8 si l'encodage du fichier existant est l'un des ASCII / UTF-8 / ANSI, mais correspond correctement à UTF-16LE et UTF-16BE.
Pour le dire différemment: en l'absence de nomenclature, Export-Csv -Appendsuppose que UTF-8 est, alors que Add-Contentsuppose ANSI.

Start-Transcript -Append correspond partiellement au codage existant: il correspond correctement aux codages avec la nomenclature , mais par défaut au codage ASCII potentiellement avec perte en l'absence d'un.


Cmdlets qui lisent (c'est-à-dire le codage utilisé en l' absence de nomenclature ):

Get-Contentet Import-PowerShellDataFilepar défaut ANSI ( Default), qui est cohérent avec Set-Content.
ANSI est également ce que le moteur PowerShell lui-même utilise par défaut lorsqu'il lit le code source à partir de fichiers.

En revanche, Import-Csv, Import-CliXmlet Select-Stringsupposer UTF-8 en l'absence d'une nomenclature.

mklement0
la source
Pouvez-vous expliquer comment >/ sont >>devenus des alias efficaces pour Out-Filedans 5.1?
Maximilian Burszley
@ TheIncorrigible1: C'est peut-être PetSerAl qui me l'a signalé, mais je ne me souviens pas où et comment. Windows PowerShell est une source fermée, mais comme la même relation de quasi-alias s'applique également à PowerShell Core, vous devriez pouvoir la trouver dans le code source de ce dernier.
mklement0
2
Je ne suis pas en désaccord, @EliaWeiss, mais c'est spécifiquement Windows PowerShell, et ils l'ont finalement fait correctement dans PowerShell Core .
mklement0
2
@Marc: VS Code et d'autres éditeurs multiplateformes modernes utilisent par défaut UTF-8, ce qui signifie cependant qu'ils interpréteront mal les fichiers encodés ANSI. Le bloc-notes utilise des heuristiques pour deviner l'encodage. Le fait est que ce n'est qu'une supposition , car tout fichier encodé en UTF-8 est également un fichier encodé en ANSI techniquement valide (mais pas l'inverse). Ce serait bien si tout sur Windows passait par défaut à UTF-8 en l'absence de nomenclature comme le font les plates-formes de type Unix, mais ce n'est pas le cas, notamment pas dans Windows PowerShell, bien que heureusement, ce soit maintenant le cas dans PowerShell Core.
mklement0
2
Pour voir votre valeur actuelle, s'il y en a, tapez simplement$PSDefaultParameterValues
Sandburg
3

Pour être bref, utilisez:

write-output "your text" | out-file -append -encoding utf8 "filename"
petits
la source