Out-File
parece forzar la lista de materiales cuando se usa UTF-8:
$MyFile = Get-Content $MyPath
$MyFile | Out-File -Encoding "UTF8" $MyPath
¿Cómo puedo escribir un archivo en UTF-8 sin BOM usando PowerShell?
encoding
powershell
utf-8
byte-order-mark
M. Dudley
fuente
fuente
Respuestas:
Usar la
UTF8Encoding
clase de .NET y pasar$False
al constructor parece funcionar:fuente
[System.IO.File]::WriteAllLines($MyPath, $MyFile)
es suficiente. EstaWriteAllLines
sobrecarga escribe exactamente UTF8 sin BOM.WriteAllLines
parece requerir$MyPath
ser absoluto.WriteAllLines
obtiene el directorio actual de[System.Environment]::CurrentDirectory
. Si abre PowerShell y luego cambia su directorio actual (usandocd
oSet-Location
),[System.Environment]::CurrentDirectory
no se cambiará y el archivo terminará en el directorio incorrecto. Puedes evitar esto por[System.Environment]::CurrentDirectory = (Get-Location).Path
.La forma correcta a partir de ahora es utilizar una solución recomendada por @Roman Kuzmin en los comentarios a @M. Dudley responde :
(También lo acorté un poco eliminando
System
aclaraciones innecesarias del espacio de nombres; se sustituirá automáticamente de forma predeterminada).fuente
[IO.File]::WriteAllLines(($filename | Resolve-Path), $content)
Pensé que esto no sería UTF, pero acabo de encontrar una solución bastante simple que parece funcionar ...
Para mí, esto da como resultado un archivo utf-8 sin bom independientemente del formato de origen.
fuente
-encoding utf8
cumplir con mis requisitos.-Encoding ASCII
evita el problema de la lista de materiales, pero obviamente solo obtienes caracteres ASCII de 7 bits . Dado que ASCII es un subconjunto de UTF-8, el archivo resultante es técnicamente también un archivo UTF-8 válido, pero todos los caracteres no ASCII en su entrada se convertirán en?
caracteres literales .-encoding utf8
aún saca UTF-8 con una lista de materiales. :(Nota: esta respuesta se aplica a Windows PowerShell ; por el contrario, en la edición multiplataforma de PowerShell Core (v6 +), UTF-8 sin BOM es la codificación predeterminada , en todos los cmdlets.
En otras palabras: si está utilizando PowerShell [Core] versión 6 o superior , obtendrá archivos UTF-8 sin BOM de forma predeterminada (que también puede solicitar explícitamente con
-Encoding utf8
/-Encoding utf8NoBOM
, mientras que obtiene con la codificación -BOM con-utf8BOM
).Para complementar la propia respuesta simple y pragmática de M. Dudley (y la reformulación más concisa de ForNeVeR ):
Por conveniencia, aquí está la función avanzada
Out-FileUtf8NoBom
, una alternativa basada en canalización que imitaOut-File
, lo que significa:Out-File
en una tubería.Out-File
.Ejemplo:
Tenga en cuenta cómo
(Get-Content $MyPath)
se incluye(...)
, lo que garantiza que todo el archivo se abra, se lea por completo y se cierre antes de enviar el resultado a través de la canalización. Esto es necesario para poder volver a escribir en el mismo archivo (actualizarlo en su lugar ).En general, sin embargo, esta técnica no es aconsejable por 2 razones: (a) todo el archivo debe caber en la memoria y (b) si se interrumpe el comando, se perderán datos.
Una nota sobre el uso de la memoria :
Código fuente de
Out-FileUtf8NoBom
(también disponible como Gist con licencia MIT ):fuente
A partir de la versión 6, powershell admite la
UTF8NoBOM
codificación tanto para el contenido del conjunto como para el archivo externo e incluso lo utiliza como codificación predeterminada.Entonces, en el ejemplo anterior, simplemente debería ser así:
fuente
$PSVersionTable.PSVersion
Cuando se usa en
Set-Content
lugar deOut-File
, puede especificar la codificaciónByte
, que se puede usar para escribir una matriz de bytes en un archivo. Esto en combinación con una codificación UTF8 personalizada que no emite la lista de materiales da el resultado deseado:La diferencia con el uso
[IO.File]::WriteAllLines()
o similar es que debería funcionar bien con cualquier tipo de elemento y ruta, no solo rutas de archivos reales.fuente
Este script convertirá, a UTF-8 sin BOM, todos los archivos .txt en DIRECTORIO1 y los enviará a DIRECTORIO2
fuente
Fuente Cómo eliminar la marca de orden de bytes UTF8 (BOM) de un archivo usando PowerShell
fuente
Si desea usar
[System.IO.File]::WriteAllLines()
, debe convertir el segundo parámetro aString[]
(si el tipo de$MyFile
esObject[]
), y también especificar la ruta absoluta con$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($MyPath)
, como:Si desea usar
[System.IO.File]::WriteAllText()
, a veces debe canalizar el segundo parámetro| Out-String |
para agregar CRLF al final de cada línea explícitamente (especialmente cuando los usa conConvertTo-Csv
):O puedes usar
[Text.Encoding]::UTF8.GetBytes()
conSet-Content -Encoding Byte
:ver: Cómo escribir el resultado de ConvertTo-Csv a un archivo en UTF-8 sin BOM
fuente
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($MyPath)
esConvert-Path $MyPath
; si desea garantizar un CRLF final, simplemente use[System.IO.File]::WriteAllLines()
incluso con una sola cadena de entrada (no es necesarioOut-String
).Una técnica que utilizo es redirigir la salida a un archivo ASCII usando el cmdlet Out-File .
Por ejemplo, a menudo ejecuto scripts SQL que crean otro script SQL para ejecutar en Oracle. Con la redirección simple (">"), la salida estará en UTF-16, lo cual no es reconocido por SQLPlus. Para evitar esto:
El script generado se puede ejecutar a través de otra sesión de SQLPlus sin preocupaciones de Unicode:
fuente
-Encoding ASCII
evita el problema de la lista de materiales, pero obviamente solo obtienes soporte para caracteres ASCII de 7 bits . Dado que ASCII es un subconjunto de UTF-8, el archivo resultante es técnicamente también un archivo UTF-8 válido, pero todos los caracteres no ASCII en su entrada se convertirán en?
caracteres literales .Cambie varios archivos por extensión a UTF-8 sin BOM:
fuente
Por alguna razón, las
WriteAllLines
llamadas seguían produciendo una lista de materiales para mí, con elUTF8Encoding
argumento BOMless y sin él. Pero lo siguiente funcionó para mí:Tuve que hacer que la ruta del archivo sea absoluta para que funcione. De lo contrario, escribió el archivo en mi escritorio. Además, supongo que esto solo funciona si sabe que su BOM es de 3 bytes. No tengo idea de cuán confiable es esperar un formato / longitud BOM determinado basado en la codificación.
Además, como está escrito, esto probablemente solo funcione si su archivo se ajusta a una matriz de PowerShell, que parece tener un límite de longitud de algún valor menor que
[int32]::MaxValue
en mi máquina.fuente
WriteAllLines
sin un argumento de codificación nunca escribe una lista de materiales en sí , pero es concebible que su cadena comience con el carácter BOM (U+FEFF
), que al escribir efectivamente creó una lista de materiales UTF-8; por ejemplo:$s = [char] 0xfeff + 'hi'; [io.file]::WriteAllText((Convert-Path t.txt), $s)
(omita el[char] 0xfeff +
para ver que no se escribe BOM).[Environment]::CurrentDirectory = $PWD.ProviderPath
, o, como una alternativa más genérica a su"$(pwd)\..."
enfoque (mejor:,"$pwd\..."
incluso mejor:"$($pwd.ProviderPath)\..."
o(Join-Path $pwd.ProviderPath ...)
), use(Convert-Path BOMthetorpedoes.txt)
U+FEFF
abstracto .Podría usar a continuación para obtener UTF8 sin BOM
fuente
ASCII
no es UTF-8, pero tampoco es la página de códigos ANSI actual, estás pensandoDefault
;ASCII
verdaderamente es una codificación ASCII de 7 bits, con puntos de código> = 128 convertidos en?
instancias literales .-Encoding ASCII
hecho, solo sea ASCII de 7 bits:'äb' | out-file ($f = [IO.Path]::GetTempFilename()) -encoding ASCII; '?b' -eq $(Get-Content $f; Remove-Item $f)
-ä
se ha transcrito a?
. Por el contrario,-Encoding Default
("ANSI") lo preservaría correctamente.Este funciona para mí (use "Predeterminado" en lugar de "UTF8"):
El resultado es ASCII sin BOM.
fuente
Default
codificación, se utilizará la página de códigos ANSI actual del sistema, que no es UTF-8, como lo solicité.