À l'aide de PowerShell pour écrire un fichier en UTF-8 sans BOM
Out-File
semble forcer le MOB lors de l'utilisation de l'UTF-8:
$MyFile = Get-Content $MyPath
$MyFile | Out-File -Encoding "UTF8" $MyPath
Comment puis-je écrire un fichier en UTF-8 sans BOM à l'aide de PowerShell?
- BOM = Marque d'Ordre d'Octet. Les trois caractères placés au début d'un fichier (0xEF,0xBB,0xBF) qui ressemblent à des ""
- C'est incroyablement frustrant. Même les modules tiers sont polluées, comme essayer de télécharger un fichier via SSH? BOM! "Oui, soyons corrompus chaque fichier unique; cela sonne comme une bonne idée." -Microsoft.
- L'encodage par défaut est UTF8NoBOM de départ avec Powershell version 6.0 docs.microsoft.com/en-us/powershell/module/...
Vous devez vous connecter pour publier un commentaire.
À l'aide .NET
UTF8Encoding
classe et en passant$False
pour le constructeur semble fonctionner:[System.IO.File]::WriteAllLines($MyPath, $MyFile)
est assez. CetteWriteAllLines
surcharge écrit exactement UTF8 sans BOM.WriteAllLines
semble exiger$MyPath
être absolue.[IO.File]::WriteAllText($MyPath, $MyFile)
.[System.Environment]::CurrentDirectory
. Si vous ouvrez PowerShell, puis de changer le répertoire courant (à l'aide decd
ouSet-Location
), puis[System.Environment]::CurrentDirectory
ne sera pas modifiée et le fichier sera à la fin dans le mauvais répertoire. Vous pouvez contourner ce problème en[System.Environment]::CurrentDirectory = (Get-Location).Path
.WriteAllLines
ajoute une nouvelle ligne à la fin d'un fichier. Mais pour faireWriteAllText
travail que vous avez à utiliser-Raw
paramètre pourGet-Content
, sinon tout le texte sera écrasé dans une seule ligne.$fileContent = Get-Content -Raw "$fileFullName"; [System.IO.File]::WriteAllText($fileFullName, $fileContent)
La bon manière que pour l'instant est d'utiliser une solution recommandée par @Romain Kouzmine dans les commentaires à @M. Dudley réponse:
(J'ai aussi de raccourcir un peu par décapage inutile
System
espace de noms de clarification - il sera remplacé automatiquement par défaut.)[IO.File]::WriteAllLines(($filename | Resolve-Path), $content)
J'ai pensé que ce ne serait pas de l'UTF, mais je viens de trouver un assez simple solution qui semble fonctionner...
Pour moi, c'résultats en utf-8 sans bom fichier quel que soit le format de la source.
-encoding utf8
à mon exigence.-Encoding ASCII
évite la NOMENCLATURE problème, mais de toute évidence vous obtenez seulement des caractères ASCII 7 bits. Étant donné que l'ASCII est un sous-ensemble de l'UTF-8, le fichier résultant est techniquement aussi valable fichier UTF-8, mais tous les caractères non-ASCII dans votre entrée sera converti littérale?
caractères.Note: Cette réponse s'applique à Windows PowerShell; en revanche, dans la croix-plate-forme de PowerShell de Base édition, UTF-8 sans BOM est le encodage par défaut.
Pour compléter M. Dudley est propre, simple et pragmatique répondre (et ForNeVeR est plus concis reformulation):
Pour des raisons de commodité, voici une fonction avancée
Out-FileUtf8NoBom
, un pipeline de remplacement qui imiteOut-File
, ce qui signifie:Out-File
dans un pipeline.Out-File
.Exemple:
Notez comment
(Get-Content $MyPath)
est enfermé dans(...)
, qui assure que le fichier est ouvert, lire dans son intégralité, et fermé avant d'envoyer le résultat à travers le pipeline. Ce qui est nécessaire pour être en mesure d'écrire de nouveau à la même fichiers (mise à jour il en place).En règle générale, cependant, cette technique n'est pas conseillé pour 2 raisons: (a) l'ensemble du dossier doit s'inscrire dans la mémoire et (b) si la commande est interrompue, les données seront perdues.
Une note sur l'utilisation de la mémoire:
Code Source de
Out-FileUtf8NoBom
(également disponible comme le MIT sous licence Gist):À partir de version 6 powershell prend en charge la
UTF8NoBOM
le codage à la fois pour set-content et out-file et même l'utilise comme encodage par défaut.Ainsi, dans l'exemple ci-dessus, il devrait être tout simplement comme ceci:
$PSVersionTable.PSVersion
Lors de l'utilisation de
Set-Content
au lieu deOut-File
, vous pouvez spécifier l'encodageByte
, qui peut être utilisé pour écrire un tableau d'octets dans un fichier. Ceci en combinaison avec un encodage UTF8 qui n'émettent pas de la NOMENCLATURE donne le résultat souhaité:La différence à l'aide de
[IO.File]::WriteAllLines()
ou similaires, c'est qu'il devrait fonctionner avec n'importe quel type d'élément et le chemin d'accès, pas uniquement les chemins d'accès de fichier.Ce script permet de convertir, en UTF-8 sans BOM, tous .les fichiers txt dans DIRECTORY1 et de sortie à DIRECTORY2
Source Comment faire pour supprimer UTF8 Marque d'Ordre des Octets (BOM) à partir d'un fichier à l'aide de PowerShell
Si vous souhaitez utiliser
[System.IO.File]::WriteAllLines()
, vous jette de la deuxième paramètre àString[]
(si le type de$MyFile
estObject[]
), et aussi spécifier le chemin d'accès absolu avec$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($MyPath)
, comme:Si vous souhaitez utiliser
[System.IO.File]::WriteAllText()
, parfois, vous devez vous pipe le deuxième paramètre en| Out-String |
pour ajouter CRLFs à la fin de chaque ligne explicitement (en Particulier lorsque vous les utilisez avecConvertTo-Csv
):Ou vous pouvez utiliser
[Text.Encoding]::UTF8.GetBytes()
avecSet-Content -Encoding Byte
:voir: Comment écrire la suite de ConvertTo-Csv dans un fichier en UTF-8 sans BOM
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($MyPath)
estConvert-Path $MyPath
; si vous voulez vous assurer une fin CRLF, il suffit d'utiliser[System.IO.File]::WriteAllLines()
même avec un unique chaîne d'entrée (pas besoin deOut-String
).Une technique que j'utilise est de rediriger la sortie vers un fichier ASCII à l'aide de la Out-File applet de commande.
Par exemple, j'ai souvent d'exécuter les scripts SQL que de créer un autre script SQL à exécuter dans Oracle. Avec une simple redirection (">"), la sortie sera en UTF-16 qui n'est pas reconnu par SQLPlus. Pour contourner ce problème:
Le script généré peut ensuite être exécuté via un autre SQLPlus session sans Unicode soucis:
-Encoding ASCII
évite la NOMENCLATURE problème, mais de toute évidence vous obtenez seulement un soutien pour des caractères ASCII 7 bits. Étant donné que l'ASCII est un sous-ensemble de l'UTF-8, le fichier résultant est techniquement aussi valable fichier UTF-8, mais tous les caractères non-ASCII dans votre entrée sera converti littérale?
caractères.Modifier plusieurs fichiers par extension de l'UTF-8 sans BOM:
Pour quelque raison que ce soit, la
WriteAllLines
appels étaient encore en production d'une NOMENCLATURE pour moi, avec les BOMlessUTF8Encoding
argument et sans elle. Mais la suite a fonctionné pour moi:J'ai dû prendre le chemin de fichier absolu pour qu'il fonctionne. Sinon, il a écrit le fichier sur mon Bureau. Aussi, je suppose que cela ne fonctionne que si vous savez que votre MOB est de 3 octets. Je n'ai aucune idée de comment fiable c'est de s'attendre à une NOMENCLATURE format/longueur basé sur le codage.
Aussi, comme l'écrit, c'est probablement ce qui ne fonctionne que si votre fichier s'inscrit dans une powershell tableau, qui semble avoir une longueur limite d'une valeur inférieure à
[int32]::MaxValue
sur ma machine.WriteAllLines
sans un encodage argument n'écrit jamais une NOMENCLATURE lui-même, mais il est concevable que votre string qui est arrivé à démarrer avec la NOMENCLATURE caractère (U+FEFF
), dont l'écriture a effectivement créé une UTF-8 BOM; par exemple:$s = [char] 0xfeff + 'hi'; [io.file]::WriteAllText((Convert-Path t.txt), $s)
(omettre la[char] 0xfeff +
de voir que aucun BOM est écrit).[Environment]::CurrentDirectory = $PWD.ProviderPath
, ou, plus générique de remplacement pour votre"$(pwd)\..."
approche (mieux:"$pwd\..."
, encore mieux:"$($pwd.ProviderPath)\..."
ou(Join-Path $pwd.ProviderPath ...)
), l'utilisation(Convert-Path BOMthetorpedoes.txt)
U+FEFF
.Celui-ci fonctionne pour moi (utilisez "par Défaut" au lieu de "UTF8"):
Le résultat est ASCII sans BOM.
Default
de l'encodage à utiliser le système actuel de la page de codes ANSI, ce qui n'est pas de l'UTF-8, comme je le nécessaire.Pourrait utiliser ci-dessous pour obtenir de l'UTF8 sans BOM
ASCII
est pas en UTF-8, mais c'est la sla non pas de la page de codes ANSI - vous êtes la pensée deDefault
;ASCII
est vraiment ASCII 7 bits de codage, avec codepoints >= 128 se converti à littérale?
instances.ASCII
signifie vraiment le défaut d'un octet codant dans cette API et généralement dans Windows. Oui, il n'est pas synchronisé avec l'officiel ASCII définition, mais est simplement un héritage historique.-Encoding ASCII
est en effet de 7 bits ASCII:'äb' | out-file ($f = [IO.Path]::GetTempFilename()) -encoding ASCII; '?b' -eq $(Get-Content $f; Remove-Item $f)
- leä
a été transcrit à un?
. En revanche,-Encoding Default
("ANSI") serait correctement le préserver.Eu le même problème. Cela a fonctionné pour moi:
Lors de l'ouverture du fichier avec le Code de Visual Studio ou Notepad++ il montre que
UTF-8
Enfin ce juste "apparaître" au travail. Lorsqu'il est ouvert avec quelques éditeur, il montre que l'UTF-8 sans BOM. Mais ce n'est pas vrai du tout. L'utilisation de la solution dans le haut de la bande de roulement. Ce un travail pour de vrai