powershell の Rename-Item
って使いにくくありませんか? -whatif
パラメータをつけ忘れて暴発したことは数知れず、つけたらつけたで出力が冗長になり読みにくい……。少なくとも私は不便に感じたので安全かつ簡単な一括リネーム用のコマンドレットを作ってみました。
プレビューを見やすくする
function Rename-Functionally {
param (
[scriptblock]$renameBlock,
[switch]$execute
)
$procTarget = $input | Where-Object {$_.GetType().Name -in @("FileInfo", "DirectoryInfo")}
$shiftJIS = [System.Text.Encoding]::GetEncoding("Shift_JIS")
$longestName = $procTarget.Name | Sort-Object {$shiftJIS.GetByteCount($_)} -Descending | Select-Object -First 1
$fill = $shiftJIS.GetByteCount($longestName) + 1
if ($execute) {
$col = "Green"
}
else {
$col = "White"
}
$procTarget | ForEach-Object {
$itemName = $_.Name
Write-Host $itemName -NoNewline -ForegroundColor DarkGray
$leftIndent = $shiftJIS.GetByteCount($itemName)
" {0}=> " -f ("=" * ($fill - $leftIndent)) | Write-Host -NoNewline
$afterName = & $renameBlock
Write-Host $afterName -ForegroundColor $col
if ($execute) {
try {
$_ | Rename-Item -NewName $afterName -ErrorAction Stop
}
catch {
Write-Host ("ERROR!: failed to rename '{0}'!" -f $itemName) -ForegroundColor Magenta
if (Test-Path $afterName) {
Write-Host "(same name exists in directory)" -ForegroundColor Magenta
}
else {
Write-Host "(other process may opening file)" -ForegroundColor Magenta
}
}
}
}
}
リネーム結果をプレビューして、 -execute
スイッチを指定した場合のみリネームを実行します。日本語が混じっていても桁が揃うように shiftJIS でバイト数をカウントしました。
置換リネームを簡単に
function Rename-Replace {
param (
[string]$from,
[string]$to,
[switch]$case,
[switch]$execute
)
if ($case) {
$reg = [regex]$from
}
else {
$reg = [regex]"(?i)$from"
}
$procTarget = $input | Where-Object {$reg.IsMatch($_.Name)}
if ($procTarget.Count -lt 1) {
return
}
$shiftJIS = [System.Text.Encoding]::GetEncoding("Shift_JIS")
$longestName = $procTarget.Name | Sort-Object {$shiftJIS.GetByteCount($_)} -Descending | Select-Object -First 1
$fill = $shiftJIS.GetByteCount($longestName) + 1
if ($execute) {
$color = "Cyan"
}
else {
$color = "White"
}
$procTarget | ForEach-Object {
$itemName = $_.Name
$replacedName = $reg.Replace($itemName, $to)
$itemName | hilight -pattern $from -plainColor "DarkGray" -color "White" -continuous
$leftIndent = $shiftJIS.GetByteCount($_.Name)
" {0}=> " -f ("=" * ($fill - $leftIndent)) | Write-Host -NoNewline -ForegroundColor Gray
Write-Host $replacedName -ForegroundColor $color
if ($execute) {
try {
$_ | Rename-Item -NewName $replacedName -ErrorAction Stop
}
catch {
Write-Host ("ERROR: failed to rename '{0}'!" -f $itemName) -ForegroundColor Magenta
if (Test-Path $replacedName) {
Write-Host "(same name exists in directory)" -ForegroundColor Magenta
}
else {
Write-Host "(other process may opening file)" -ForegroundColor Magenta
}
}
}
}
}
単純に文字列を置換するだけであればパラメータ指定ももう少し楽にできます。
hilight
は 自作コマンドレット のエイリアスです。
挿入リネームを簡単に
function Rename-Insert {
param (
[string]$insert,
[int]$position = -1,
[switch]$execute
)
if ($position -eq 0) {
Write-Host "parameter '-position' do not accept 0!" -ForegroundColor Magenta
return
}
$shiftJIS = [System.Text.Encoding]::GetEncoding("Shift_JIS")
$procTarget = $input | Where-Object {$_.GetType().Name -in @("FileInfo", "DirectoryInfo")}
if ($position -lt 0) {
$longestBaseName = $procTarget.Basename | Sort-Object {$shiftJIS.GetByteCount($_)} -Descending | Select-Object -First 1
$width = $shiftJIS.GetByteCount($longestBaseName)
}
if ($execute) {
$color = "Green"
}
else {
$color = "White"
}
$procTarget | ForEach-Object {
$itemName = $_.Name
try{
if ($position -lt 0) {
$pre = ($_.Basename).substring(0, ($_.Basename).length + $position + 1)
$post = ($_.Basename).substring( ($_.Basename).length + $position + 1)
$newName = $pre + $insert + $post + $_.Extension
$fill = $width - $shiftJIS.GetByteCount($_.Basename) + 1
Write-Host -NoNewline (" " * $fill)
Write-Host $pre -NoNewline -ForegroundColor DarkGray
Write-Host $insert -NoNewline -ForegroundColor $color
Write-Host ($post + $_.Extension) -ForegroundColor DarkGray
}
else {
$newName = ($itemName).Insert($position - 1, $insert)
Write-Host ($itemName).substring(0, $position - 1) -NoNewline -ForegroundColor DarkGray
Write-Host $insert -ForegroundColor $color -NoNewline
Write-Host ($itemName).substring($position - 1) -ForegroundColor DarkGray
}
if ($execute) {
$_ | Rename-Item -NewName $newName -ErrorAction Stop
}
}
catch {
Write-Host ("ERROR: failed to insert '{0}' to position {1} of '{2}'." -f $insert, $position, $itemName) -ForegroundColor Magenta
}
}
}
プレビューで末尾に挿入する場合に右揃えになるように工夫してみました。