Out-File
scheint die Stückliste bei Verwendung von UTF-8 zu erzwingen:
$MyFile = Get-Content $MyPath
$MyFile | Out-File -Encoding "UTF8" $MyPath
Wie kann ich mit PowerShell eine Datei in UTF-8 ohne Stückliste schreiben?
encoding
powershell
utf-8
byte-order-mark
M. Dudley
quelle
quelle
Antworten:
Die Verwendung der .NET-
UTF8Encoding
Klasse und die Übergabe$False
an den Konstruktor scheint zu funktionieren:quelle
[System.IO.File]::WriteAllLines($MyPath, $MyFile)
reicht aus. DieseWriteAllLines
Überladung schreibt genau UTF8 ohne Stückliste.WriteAllLines
scheint$MyPath
.WriteAllLines
das aktuelle Verzeichnis ab[System.Environment]::CurrentDirectory
. Wenn Sie PowerShell öffnen und dann Ihr aktuelles Verzeichnis ändern (mitcd
oderSet-Location
),[System.Environment]::CurrentDirectory
wird dies nicht geändert und die Datei befindet sich im falschen Verzeichnis. Sie können dies umgehen, indem Sie[System.Environment]::CurrentDirectory = (Get-Location).Path
.Der richtige Weg ist ab sofort, eine von @Roman Kuzmin in Kommentaren zu @M empfohlene Lösung zu verwenden. Dudley Antwort :
(Ich habe es auch ein wenig verkürzt, indem ich unnötige
System
Namespace-Klarstellungen entfernt habe - es wird standardmäßig automatisch ersetzt.)quelle
[IO.File]::WriteAllLines(($filename | Resolve-Path), $content)
Ich dachte, das wäre kein UTF, aber ich habe gerade eine ziemlich einfache Lösung gefunden, die zu funktionieren scheint ...
Für mich führt dies zu einem utf-8 ohne bom-Datei, unabhängig vom Quellformat.
quelle
-encoding utf8
für meine Anforderung verwendet.-Encoding ASCII
vermeidet das Stücklistenproblem, aber Sie erhalten offensichtlich nur 7-Bit-ASCII-Zeichen . Da ASCII eine Teilmenge von UTF-8 ist, ist die resultierende Datei technisch auch eine gültige UTF-8 - Datei, aber alle Nicht-ASCII - Zeichen in Ihrer Eingabe werden wörtliche umgewandelt werden?
Zeichen .-encoding utf8
immer noch UTF-8 mit einer Stückliste aus. :(Hinweis: Diese Antwort gilt für Windows PowerShell . Im Gegensatz dazu ist in der plattformübergreifenden PowerShell Core Edition (Version 6 +) UTF-8 ohne Stückliste die Standardcodierung für alle Cmdlets.
Mit anderen Worten: Wenn Sie PowerShell [Core] Version 6 oder höher verwenden , erhalten Sie standardmäßig Stücklistenlose UTF-8-Dateien (die Sie auch explizit mit
-Encoding utf8
/ anfordern können-Encoding utf8NoBOM
, während Sie mit -BOM-Codierung mit erhalten-utf8BOM
).Zur Ergänzung von M. Dudleys eigener einfacher und pragmatischer Antwort (und der präziseren Neuformulierung von ForNeVeR) ):
Der Einfachheit halber ist hier die erweiterte Funktion
Out-FileUtf8NoBom
, eine Pipeline-basierte Alternative, die nachahmtOut-File
, was bedeutet:Out-File
in einer Pipeline verwenden.Out-File
.Beispiel:
Beachten Sie, wie
(Get-Content $MyPath)
eingeschlossen ist(...)
, wodurch sichergestellt wird, dass die gesamte Datei geöffnet, vollständig gelesen und geschlossen wird, bevor das Ergebnis über die Pipeline gesendet wird. Dies ist erforderlich, um in dieselbe Datei zurückschreiben zu können (aktualisieren Sie sie an Ort und Stelle ).Im Allgemeinen ist diese Technik jedoch aus zwei Gründen nicht ratsam: (a) Die gesamte Datei muss in den Speicher passen, und (b) wenn der Befehl unterbrochen wird, gehen Daten verloren.
Ein Hinweis zur Speichernutzung :
Quellcode von
Out-FileUtf8NoBom
(auch als MIT-lizenzierte Gist erhältlich ):quelle
Ab Version 6 unterstützt Powershell die
UTF8NoBOM
Codierung sowohl für Set-Content als auch für Out-File und verwendet diese sogar als Standardcodierung.Im obigen Beispiel sollte es einfach so sein:
quelle
$PSVersionTable.PSVersion
Bei Verwendung von
Set-Content
anstelle vonOut-File
können Sie die Codierung angebenByte
, mit der ein Byte-Array in eine Datei geschrieben werden kann. Dies in Kombination mit einer benutzerdefinierten UTF8-Codierung, die die Stückliste nicht ausgibt, ergibt das gewünschte Ergebnis:Der Unterschied zur Verwendung
[IO.File]::WriteAllLines()
oder ähnlichem besteht darin, dass es mit jeder Art von Element und Pfad gut funktionieren sollte, nicht nur mit tatsächlichen Dateipfaden.quelle
Dieses Skript konvertiert alle TXT-Dateien in DIRECTORY1 in UTF-8 ohne Stückliste und gibt sie in DIRECTORY2 aus
quelle
Quelle Entfernen von UTF8-Byte-Bestellmarken (BOM) aus einer Datei mit PowerShell
quelle
Wenn Sie verwenden möchten
[System.IO.File]::WriteAllLines()
, sollten Sie den zweiten Parameter inString[]
(wenn der Typ von$MyFile
istObject[]
) umwandeln und auch den absoluten Pfad mit angeben$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($MyPath)
, wie:Wenn Sie verwenden möchten
[System.IO.File]::WriteAllText()
, sollten Sie manchmal den zweiten Parameter| Out-String |
einfügen, um CRLFs explizit am Ende jeder Zeile hinzuzufügen (insbesondere, wenn Sie sie mit verwendenConvertTo-Csv
):Oder Sie können verwenden
[Text.Encoding]::UTF8.GetBytes()
mitSet-Content -Encoding Byte
:Siehe: So schreiben Sie das Ergebnis von ConvertTo-Csv in eine Datei in UTF-8 ohne Stückliste
quelle
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($MyPath)
istConvert-Path $MyPath
; Wenn Sie eine nachfolgende CRLF sicherstellen möchten, verwenden Sie einfach[System.IO.File]::WriteAllLines()
auch eine einzelne Eingabezeichenfolge (keine NotwendigkeitOut-String
).Eine Technik, die ich verwende, besteht darin, die Ausgabe mithilfe des Cmdlets Out-File in eine ASCII -Datei umzuleiten.
Zum Beispiel führe ich häufig SQL-Skripte aus, die ein anderes SQL-Skript erstellen, das in Oracle ausgeführt werden soll. Bei einfacher Umleitung (">") erfolgt die Ausgabe in UTF-16, das von SQLPlus nicht erkannt wird. Um dies zu umgehen:
Das generierte Skript kann dann ohne Unicode-Probleme über eine andere SQLPlus-Sitzung ausgeführt werden:
quelle
-Encoding ASCII
vermeidet das Stücklistenproblem, aber Sie erhalten offensichtlich nur Unterstützung für 7-Bit-ASCII-Zeichen . Da ASCII eine Teilmenge von UTF-8 ist, ist die resultierende Datei technisch auch eine gültige UTF-8 - Datei, aber alle Nicht-ASCII - Zeichen in Ihrer Eingabe werden wörtliche umgewandelt werden?
Zeichen .Ändern Sie mehrere Dateien durch Erweiterung in UTF-8 ohne Stückliste:
quelle
Aus irgendeinem Grund produzierten die
WriteAllLines
Anrufe immer noch eine Stückliste für mich, mit demUTF8Encoding
Argument Stücklistenlos und ohne. Aber das Folgende hat bei mir funktioniert:Ich musste den Dateipfad absolut machen, damit er funktioniert. Andernfalls wurde die Datei auf meinen Desktop geschrieben. Außerdem funktioniert dies vermutlich nur, wenn Sie wissen, dass Ihre Stückliste 3 Byte umfasst. Ich habe keine Ahnung, wie zuverlässig es ist, ein bestimmtes Stücklistenformat / eine bestimmte Stücklistenlänge basierend auf der Codierung zu erwarten.
Wie geschrieben, funktioniert dies wahrscheinlich nur, wenn Ihre Datei in ein Powershell-Array passt, dessen Längenbegrenzung um einen Wert niedriger zu sein scheint als
[int32]::MaxValue
auf meinem Computer.quelle
WriteAllLines
ohne eine Codierung Argument schreibt nie eine Stückliste selbst , aber es ist denkbar , dass Ihre Zeichenfolge mit der BOM starten passierten Zeichen (U+FEFF
), die effektiv erstellt einen UTF-8 BOM auf dem Schreiben; zB:$s = [char] 0xfeff + 'hi'; [io.file]::WriteAllText((Convert-Path t.txt), $s)
(lassen Sie das weg, um[char] 0xfeff +
zu sehen, dass keine Stückliste geschrieben ist).[Environment]::CurrentDirectory = $PWD.ProviderPath
oder als allgemeinere Alternative zu Ihrem"$(pwd)\..."
Ansatz (besser :"$pwd\..."
, noch besser:"$($pwd.ProviderPath)\..."
oder(Join-Path $pwd.ProviderPath ...)
)(Convert-Path BOMthetorpedoes.txt)
U+FEFF
.Könnte unten verwenden, um UTF8 ohne Stückliste zu erhalten
quelle
ASCII
nicht UTF-8 ist, aber es ist auch nicht die aktuelle ANSI-Codepage - Sie denken daranDefault
;ASCII
Es handelt sich tatsächlich um eine 7-Bit-ASCII-Codierung, bei der Codepunkte> = 128 in Literalinstanzen konvertiert?
werden.-Encoding ASCII
es sich tatsächlich nur um 7-Bit-ASCII handelt:'äb' | out-file ($f = [IO.Path]::GetTempFilename()) -encoding ASCII; '?b' -eq $(Get-Content $f; Remove-Item $f)
- Dasä
wurde in a transkribiert?
. Im Gegensatz dazu würde-Encoding Default
("ANSI") es korrekt beibehalten.Dieser funktioniert für mich (verwenden Sie "Standard" anstelle von "UTF8"):
Das Ergebnis ist ASCII ohne Stückliste.
quelle
Default
Codierung angegeben ist, wird die aktuelle ANSI-Codepage des Systems verwendet, die nicht wie erforderlich UTF-8 ist.