他のフォルダを含むテキストファイルを含むフォルダがあり、これらにもいくつかのテキストファイルが含まれています。 PowerShellでこれらすべてのファイルを再帰的にUTF-8エンコーディングに変換し、このプロセス中にフォルダー構造を保持する必要があります。私はこれを試しました:
foreach( $i in get-childitem -recurse -name ) {
get-content $i | out-file -encoding utf8 -filepath some_folder/$i
}
ただし、機能せず、フォルダの階層を再現できません。この問題にどのように対処しますか?
これを試してください。
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
}
get-content $i | out-file -encoding utf8 -filepath $dest
}
ファイルの完全パスを取得し、現在のディレクトリを目的のディレクトリに置き換えます。たとえば、このコマンドはディレクトリC:\1\
($PWD = C:\1\
)で実行します。ファイルC:\1\2\file.txt
が見つかると、$dest
のsome_folder\2\file.txt
が表示されます。
最初のifブロックが存在するため、ディレクトリを変換しようとはしません。
ディレクトリがまだ存在しない場合は作成する必要があります-私はもともとそれを忘れていました。
BOMなしのUTF8が必要な場合は、get-content $i | out-file -encoding utf8 -filepath $dest
行を次の( source )に置き換えます。
$filecontents = Get-Content $i
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
[System.IO.File]::WriteAllLines($i, $filecontents, $Utf8NoBomEncoding)
これは、ファイルを再度書き込む前にファイル全体をメモリに読み込むため、大きなファイルの場合はあまりパフォーマンスが良くない場合があることに注意してください。効率が必要な場合は、1行ずつ、または一度に特定のバイト数を読み取ることができます。ただし、私はむしろその時点でC#で簡単なプログラムを記述したいだけです(とにかくPSで.NET関数を使用しているためです)。
使用法:& "TextEncoding.ps1" -path "c:\ windows\temps\folder1" -encoding "UTF8"
これが私が作成したスクリプトです:
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[string]$path,
[Parameter(Mandatory=$false)]
[string]$dest = $path,
[Parameter(Mandatory=$true)]
[string]$encoding
)
function Set-Encoding(){
#ensure it is a valid path
if(-not(Test-Path -Path $path)){
throw "File or directory not found at {0}" -f $path
}
#if the path is a file, else a directory
if(Test-Path $path -PathType Leaf){
#if the provided path equals the destination
if($path -eq $dest){
#get file extension
$ext = [System.IO.Path]::GetExtension($path)
#create destination
$dest = $path.Replace([System.IO.Path]::GetFileName($path), ("temp_encoded{0}" -f $ext))
#output to file with encoding
Get-Content $path | Out-File -FilePath $dest -Encoding $encoding -Force
#copy item to original path to overwrite (note move-item loses encoding)
Copy-Item -Path $dest -Destination $path -Force -PassThru | ForEach-Object { Write-Output -inputobject ("{0} encoded {1}" -f $encoding, $_) }
#remove the extra file
Remove-Item $dest
}else{
#output to file with encoding
Get-Content $path | Out-File -FilePath $dest -Encoding $encoding -Force
}
}else{
#get all the files recursively
foreach($i in Get-ChildItem -Path $path -Recurse) {
if ($i.PSIsContainer) {
continue
}
#get file extension
$ext = [System.IO.Path]::GetExtension($i)
#create destination
$dest = "$path\temp_encoded{0}" -f $ext
#output to file with encoding
Get-Content $i.FullName | Out-File -FilePath $dest -Encoding $encoding -Force
#copy item to original path to overwrite (note move-item loses encoding)
Copy-Item -Path $dest -Destination $i.FullName -Force -PassThru | ForEach-Object { Write-Output -inputobject ("{0} encoded {1}" -f $encoding, $_) }
#remove the extra file
Remove-Item $dest
}
}
}
Set-Encoding