J'essaie de faire une chose simple et simple: changer l'encodage de fichiers de n'importe quoi en UTF-8 sans BOM. J'ai trouvé plusieurs scripts qui font cela et le seul qui a vraiment fonctionné pour moi est celui-ci: https://superuser.com/questions/397890/convert-text-files-recursively-to-utf-8-in- Powershell # answer-397915 .
Cela a fonctionné comme prévu, mais j'ai besoin des fichiers générés sans nomenclature. J'ai donc essayé de modifier un peu le script en ajoutant la solution donnée à cette question: Utilisation de PowerShell pour écrire un fichier au format UTF-8 sans la nomenclature
Ceci est mon dernier script:
foreach ($i in Get-ChildItem -Recurse) {
if ($i.PSIsContainer) {
continue
}
$dest = $i.Fullname.Replace($PWD, "some_folder")
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
if (!(Test-Path $(Split-Path $dest -Parent))) {
New-Item $(Split-Path $dest -Parent) -type Directory
}
get-content $i | out-file -encoding $Utf8NoBomEncoding -filepath $dest
}
Le problème est que powershell me renvoie une erreur concernant la ligne System.Text.UTF8Encoding($False)
et se plaint d'un paramètre incorrect:
Il n'est pas possible de valider l'argument sur le paramètre 'Encoding'. L'argument "System.Text.UTF8Encoding" n'appartient pas au groupe "unicode, utf7, utf8, utf32, ascii" spécifié par l'attribut ValidateSet.
Je me demande si quelque chose me manque, comme la version PowerShell ou quelque chose comme ça. Je n'avais jamais codé de script Powershell auparavant, alors je suis totalement perdu avec cela. Et je dois changer l'encodage de ces fichiers, il y en a des centaines, je ne voudrais pas le faire moi-même un à un.
En fait, j'utilise la version 2.0 fournie avec Windows 7.
Merci d'avance!
EDIT 1
J'ai essayé le code suivant, suggéré par @LarsTruijens et d'autres publications:
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
foreach ($i in Get-ChildItem -Recurse) {
if ($i.PSIsContainer) {
continue
}
$dest = $i.Fullname.Replace($PWD, "some_folder")
if (!(Test-Path $(Split-Path $dest -Parent))) {
New-Item $(Split-Path $dest -Parent) -type Directory
}
$content = get-content $i
[System.IO.File]::WriteAllLines($dest, $content, $Utf8NoBomEncoding)
}
Cela me donne une exception, se plaindre de l'un des paramètres de WriteAllLines: "Exception on calling 'WriteAllLines' with 3 arguments. The value can't be null". Parameter name: contents
. Le script crée tous les dossiers, cependant. Mais ils sont tous vides.
EDIT 2
Une chose intéressante à propos de cette erreur est que le paramètre "content" n’est pas nul. Si je produis la valeur de la variable $ content (en utilisant Write-Host), les lignes sont là. Alors, pourquoi devient-il nul lorsqu'il est passé à la méthode WriteAllLines?
EDIT 3
J'ai ajouté une vérification de contenu à la variable, le script ressemble donc à ceci:
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
foreach ($i in Get-ChildItem -Recurse) {
if ($i.PSIsContainer) {
continue
}
$dest = $i.Fullname.Replace($PWD, "some_folder")
if (!(Test-Path $(Split-Path $dest -Parent))) {
New-Item $(Split-Path $dest -Parent) -type Directory
}
$content = get-content $i
if ( $content -ne $null ) {
[System.IO.File]::WriteAllLines($dest, $content, $Utf8NoBomEncoding)
}
else {
Write-Host "No content from: $i"
}
}
Désormais, chaque itération renvoie le message "Aucun contenu de: $ i", mais le fichier n'est pas vide. Il y a encore une erreur: Get-content: can't find the path 'C:\root\FILENAME.php' because it doesn't exists.
Il semble que le système cherche les fichiers dans le répertoire racine et non dans les sous-dossiers. Il semble pouvoir extraire le nom de fichier des dossiers enfants, mais essaie de le lire à partir de la racine.
EDIT 4 - Version de travail finale
Après avoir eu du mal à suivre et à suivre les conseils que je suis arrivé ici, spécialement de @LarsTruijens et @AnsgarWiechers, j'ai finalement réussi. J'ai dû changer la façon dont je récupérais le répertoire à partir de $ PWD et définir des noms fixes pour les dossiers. Après cela, cela a parfaitement fonctionné.
Voilà, pour tous ceux qui pourraient être intéressés:
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
$source = "path"
$destination = "some_folder"
foreach ($i in Get-ChildItem -Recurse -Force) {
if ($i.PSIsContainer) {
continue
}
$path = $i.DirectoryName -replace $source, $destination
$name = $i.Fullname -replace $source, $destination
if ( !(Test-Path $path) ) {
New-Item -Path $path -ItemType directory
}
$content = get-content $i.Fullname
if ( $content -ne $null ) {
[System.IO.File]::WriteAllLines($name, $content, $Utf8NoBomEncoding)
} else {
Write-Host "No content from: $i"
}
}
Vous n'avez pas suivi toute la réponse dans ici . Vous avez oublié la partie WriteAllLines.
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
foreach ($i in Get-ChildItem -Recurse) {
if ($i.PSIsContainer) {
continue
}
$dest = $i.Fullname.Replace($PWD, "some_folder")
if (!(Test-Path $(Split-Path $dest -Parent))) {
New-Item $(Split-Path $dest -Parent) -type Directory
}
$content = get-content $i
[System.IO.File]::WriteAllLines($dest, $content, $Utf8NoBomEncoding)
}
La moitié de la réponse est dans le message d'erreur. Il vous indique les valeurs possibles acceptées par le paramètre Encoding, dont utf8.
... out-file -encoding utf8
J'ai fait quelques corrections
et tout emballé dans une applet de commande:
<#
.SYNOPSIS
Encode-Utf8
.DESCRIPTION
Re-Write all files in a folder in UTF-8
.PARAMETER Source
directory path to recursively scan for files
.PARAMETER Destination
directory path to write files to
#>
[CmdletBinding(DefaultParameterSetName="Help")]
Param(
[Parameter(Mandatory=$true, Position=0, ParameterSetName="Default")]
[string]
$Source,
[Parameter(Mandatory=$true, Position=1, ParameterSetName="Default")]
[string]
$Destination,
[Parameter(Mandatory=$false, Position=0, ParameterSetName="Help")]
[switch]
$Help
)
if($PSCmdlet.ParameterSetName -eq 'Help'){
Get-Help $MyInvocation.MyCommand.Definition -Detailed
Exit
}
if($PSBoundParameters['Debug']){
$DebugPreference = 'Continue'
}
$Source = Resolve-Path $Source
if (-not (Test-Path $Destination)) {
New-Item -ItemType Directory -Path $Destination -Force | Out-Null
}
$Destination = Resolve-Path $Destination
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
foreach ($i in Get-ChildItem $Source -Recurse -Force) {
if ($i.PSIsContainer) {
continue
}
$path = $i.DirectoryName.Replace($Source, $Destination)
$name = $i.Fullname.Replace($Source, $Destination)
if ( !(Test-Path $path) ) {
New-Item -Path $path -ItemType directory
}
$content = get-content $i.Fullname
if ( $content -ne $null ) {
[System.IO.File]::WriteAllLines($name, $content, $Utf8NoBomEncoding)
} else {
Write-Host "No content from: $i"
}
}
Cette approche crée la structure de dossiers complète avant de copier les fichiers dans UTF-8 à partir du répertoire actuel. À la fin, nous échangeons les noms de répertoire parent.
$destination = "..\DestinationFolder"
Remove-item $destination -Recurse -Force
robocopy $PWD $destination /e /xf *.*
foreach($i in Get-ChildItem -Recurse) {
if ($i.PSIsContainer) {
continue
}
$originalContent = $i.Fullname
$dest = $i.Fullname.Replace($PWD, $destination)
if (!(Test-Path $(Split-Path $dest -Parent))) {
New-Item $(Split-Path $dest -Parent) -type Directory
}
get-content $originalContent | out-file -encoding utf8 -filepath $dest
}
cd c:\MyDirectoryWithCrazyCharacterEncodingAndUnicode
Copiez et collez le script dans vos fenêtres Powershell
foreach($FileNameInUnicodeOrWhatever in get-childitem)
{
$FileName = $FileNameInUnicodeOrWhatever.Name
$TempFile = "$($FileNameInUnicodeOrWhatever.Name).ASCII"
get-content $FileNameInUnicodeOrWhatever | out-file $FileNameInUnicodeOrWhatever -Encoding ASCII
remove-item $FileNameInUnicodeOrWhatever
rename-item $TempFile $FileNameInUnicodeOrWhatever
write-output $FileNameInUnicodeOrWhatever "converted to ASCII ->" $TempFile
}