LoginSignup
2
3

More than 3 years have passed since last update.

【powershell】Rename-Item を使いやすくする

Last updated at Posted at 2020-04-29

powershell の Rename-Item って使いにくくありませんか? -whatif パラメータをつけ忘れて暴発したことは数知れず、つけたらつけたで出力が冗長になり読みにくい……。少なくとも私は不便に感じたので安全かつ簡単な一括リネーム用のコマンドレットを作ってみました。

プレビューを見やすくする

renf.png

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 でバイト数をカウントしました。

置換リネームを簡単に

repn.png

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自作コマンドレット のエイリアスです。

挿入リネームを簡単に

rins1.png
rins2.png

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
        }
    }
}

プレビューで末尾に挿入する場合に右揃えになるように工夫してみました。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3