131 votes

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

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

Il est possible de le faire au cas par cas en remplaçant l'option >foo.txt syntaxe avec | out-file foo.txt -encoding utf8 mais c'est gênant de devoir le répéter à chaque fois.

La manière persistante de définir des choses dans PowerShell est de les mettre dans \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 défini avec $PSDefaultParameterValues = @{'Out-File:Encoding' = 'utf8'} mais j'ai essayé ça et ça n'a eu aucun effet.

https://blogs.msdn.microsoft.com/powershell/2006/12/11/outputencoding-to-the-rescue/ qui parle de $OutputEncoding semble à première vue être pertinent, mais il parle d'une sortie codée en ASCII, ce qui n'est pas ce qui se passe réellement.

Comment configurer PowerShell pour utiliser UTF-8 ?

193voto

mklement0 Points 12597

Note : Ce qui suit s'applique à Windows PowerShell .
Voir le prochaine section pour le système multiplateforme PowerShell Core (v6+) édition.

  • Sur PSv5.1 ou supérieur> et >> sont effectivement des alias de Out-File vous pouvez définir l'encodage par défaut pour > / >> / Out-File via le $PSDefaultParameterValues variable de préférence :

    • $PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'
  • Sur PSv5.0 ou inférieur vous ne peut pas changer l'encodage pour > / >> mais, le PSv3 ou plus la technique ci-dessus fait pour les appels explicites à Out-File .
    (Le $PSDefaultParameterValues La variable de préférence a été introduite dans PSv3.0).

  • Sur PSv3.0 ou plus si vous voulez définir l'encodage par défaut pour tous Les cmdlets qui prennent en charge
    un -Encoding paramètre
    (qui dans PSv5.1+ inclut > et >> ), utiliser :

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

Si vous placez cette commande dans votre $PROFILE des cmdlets tels que comme Out-File et Set-Content utilisera l'encodage UTF-8 par défaut, mais notez que cela fait de lui une session-paramétrage global qui affectera toutes les commandes / scripts qui ne spécifient pas explicitement un encodage via leur fichier -Encoding paramètre.

De même, assurez-vous d'inclure de telles commandes dans votre scripts ou modules que vous voulez vous comporter de la même manière de sorte qu'ils se comportent de la même manière même lorsqu'ils sont exécutés par un autre utilisateur ou une autre machine. mondial changement, utilisez le formulaire suivant pour créer un local copie de $PSDefaultParameterValues :

  • $PSDefaultParameterValues = @{ '*:Encoding' = 'utf8' }

Caveat : PowerShell, à partir de la version 5.1, invariablement crée des fichiers UTF-8 _avec un (pseudo) nomenclature_ ce qui n'est habituel que dans les Windows monde - Unix -ne reconnaissent pas cette nomenclature (voir en bas de page). ce poste pour des solutions de contournement qui créent des fichiers UTF-8 sans BOM.

Pour un Résumé du comportement très incohérent du codage des caractères par défaut dans de nombreuses commandes standard de Windows PowerShell. voir la section inférieure.


L'automatique $OutputEncoding La variable est sans rapport et s'applique uniquement à la manière dont PowerShell communique avec programmes externes (quel encodage PowerShell utilise lorsqu'il leur envoie des chaînes) - cela n'a rien à voir avec l'encodage que les opérateurs de redirection de sortie et les cmdlets PowerShell utilisent pour enregistrer dans des fichiers.


Lecture facultative : La perspective multiplateforme : PowerShell Core :

PowerShell est désormais multiplateforme par l'intermédiaire de son PowerShell Core édition, dont l'encodage - judicieusement - La valeur par défaut est UTF-8 sans BOM en accord avec les plateformes de type Unix.

  • Cela signifie que les fichiers de code source sans BOM sont supposés être UTF-8, et que l'utilisation de l'option > / Out-File / Set-Content La valeur par défaut est Sans nomenclature UTF-8 ; l'utilisation explicite de l'option utf8 -Encoding Cet argument crée aussi Sans nomenclature UTF-8, mais vous pouvez choisir de créer des fichiers avec la pseudo-BOM avec le utf8bom valeur.

  • 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 résultat *.ps1 sera généralement pas ont un pseudo-BOM UTF-8 :

    • Cela fonctionne bien avec PowerShell Core .
    • Il peut se briser sur 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 en UTF-8. avec nomenclature .
      Sans la BOM, Windows PowerShell interprète (mal) votre script comme étant codé dans l'ancienne page de code "ANSI" (déterminée par les paramètres locaux du système pour les applications pré-Unicode ; par exemple, Windows-1252 sur les systèmes anglo-saxons).
  • À l'inverse, les dossiers qui faire ont le pseudo-BOM UTF-8 peuvent être problématiques sur les plates-formes de type Unix, car ils entraînent des utilitaires Unix tels que cat , sed et awk - et même certains éditeurs tels que gedit - à faire passer la pseudo-BOM par c'est-à-dire de le traiter comme 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 de caractères en bash avec, disons, text=$(cat file) ou text=$(<file) - la variable résultante contiendra la pseudo-BOM comme les 3 premiers octets.

Comportement d'encodage par défaut incohérent dans Windows PowerShell :

Malheureusement, le codage des caractères par défaut utilisé dans Windows PowerShell est très incohérent ; la version multi-plateforme de PowerShell Core comme nous l'avons vu dans la section précédente, a mis fin à cette situation de façon louable.

Note :

  • Ce qui suit n'a pas l'ambition de couvrir tous cmdlets standard.

  • La recherche des noms de cmdlets sur Google pour trouver les rubriques d'aide correspondantes vous permet désormais d'accéder à l'aide 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 Windows PowerShell version.

  • À l'heure où nous écrivons ces lignes, la documentation affirme souvent à tort que l'ASCII est le codage par défaut de Windows PowerShell - cf. ce problème de documentation GitHub .


Cmdlets qui écrire :

Out-File et > / >> créer "Unicode" - UTF-16LE - par défaut - dans lesquels chaque caractère de la gamme ASCII (aussi) est représenté par 2 octets - qui diffère notamment de Set-Content / Add-Content (voir point suivant) ; New-ModuleManifest et Export-CliXml crée également des fichiers UTF-16LE.

Set-Content (et Add-Content si le fichier n'existe pas encore / est vide) utilise le codage ANSI (le codage spécifié par la page de code ANSI de la locale du système actif, que PowerShell appelle Default ).

Export-Csv crée en effet des fichiers ASCII, comme documenté, mais voir les notes concernant les fichiers ASCII. -Append ci-dessous.

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

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

Le site Send-MailMessage Le sujet d'aide affirme également que le codage ASCII est le codage par défaut - je n'ai pas personnellement vérifié cette affirmation.

Start-Transcript invariablement crée des fichiers UTF-8 avec Nomenclature, mais voir les notes concernant -Append ci-dessous.

Re commande que ajouter à un fichier existant :

>> / Out-File -Append faire pas de tentent de faire correspondre l'encodage des données d'un fichier. contenu existant . C'est-à-dire qu'ils appliquent aveuglément leur encodage par défaut, à moins d'une instruction contraire avec la commande -Encoding ce qui n'est pas une option avec >> (sauf indirectement dans PSv5.1+, via $PSDefaultParameterValues comme indiqué ci-dessus). En résumé, vous devez connaître l'encodage du contenu d'un fichier existant et l'ajouter en utilisant ce même encodage.

Add-Content est l'exception louable : en l'absence d'une clause explicite de -Encoding 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 l'encodage ANSI qui est appliqué si le contenu existant n'a pas de BOM, alors que c'est UTF-8 dans PowerShell Core.

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

Export-Csv -Append partiellement correspond à l'encodage existant : il ajoute aveuglément UTF-8 si l'encodage du fichier existant est un encodage parmi ASCII/UTF-8/ANSI, mais correspond correctement à UTF-16LE et UTF-16BE.
En d'autres termes, en l'absence de nomenclature, Export-Csv -Append suppose qu'UTF-8 l'est, alors que Add-Content suppose l'ANSI.

Start-Transcript -Append partiellement correspond à l'encodage existant : Il correspond correctement aux encodages avec nomenclature mais, en l'absence d'un tel codage, il utilise par défaut un codage ASCII avec perte potentielle.


Cmdlets qui lire (c'est-à-dire l'encodage utilisé dans l'application absence de nomenclature ) :

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

En revanche, Import-Csv , Import-CliXml et Select-String suppose UTF-8 en l'absence de nomenclature.

0 votes

Pouvez-vous expliquer comment > / >> sont devenus des pseudonymes effectifs pour Out-File en 5.1 ?

0 votes

@TheIncorrigible1 : C'est peut-être PetSerAl qui me l'a fait remarquer, mais je ne me souviens plus où et comment. Windows PowerShell est closed-source, mais comme la même relation de quasi-alias s'applique aussi à PowerShell Core, vous devriez pouvoir la trouver dans le code source de ce dernier.

1 votes

Existe-t-il un moyen de forcer la non-préparation de la nomenclature sur Win10 ?

1voto

pbies Points 233

Pour être bref, utilisez :

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

Vous pouvez mettre des parties du script entre accolades pour pouvoir rediriger la sortie de quelques commandes :

{
  command 1
  command 2
} | out-file -append -encoding utf8 "filename"

0 votes

Pour citer la question : "Il est possible de le faire au cas par cas en remplaçant le >foo.txt syntaxe avec | out-file foo.txt -encoding utf8 mais c'est gênant de devoir le répéter à chaque fois." En d'autres termes, vous suggérez précisément ce que le PO essaie d'éviter.

1 votes

Je pense -append doit être supprimé

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X