0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ファイル名の頭ゼロ補正.ps1

Posted at

1. スクリプト概要

スクリプト名: ファイル名の頭ゼロ補正.ps1
対象フォルダ内のファイル名に含まれる数字に頭ゼロを追加し、桁数を統一します

2. 処理と目的

処理の流れ
 1. 処理対象のフォルダを指定します
 2. 対象フォルダ内のファイルの一覧を取得します
 3. 統一する数字の桁数を指定します(未指定の場合は、手順2で取得したファイル名に含まれる数字の最大桁数)
 4. ファイル名の数字の桁数を統一した新しいファイル名を作成します
 5. 変更前後のファイル名をグリッドで表示し、変更するファイルを選択します
 6. 選択されたファイルの名前を変更します

目的
 「1」から「10」のような連番が付いているファイルを名前順で表示する際、ソフトウェアによって表示順序に差異が生じることがあります。このスクリプトは、その差異をなくし、常に意図した順序で表示されるようにするために使用します

3. 動作環境と要件

PowerShellのバージョン
7.0以上

OS
Windows10

必要なモジュール
特になし

必要な権限
特になし

その他の設定
特になし

4. 使用方法

基本的な実行方法
スクリプトコードを拡張子ps1で保存してPowershellで実行してください。
ファイルを保存する際は、文字コードをUTF8 BOM付にしてください。

パラメータ
なし

使用例

  1. コマンドラインでpwsh ファイル名の頭ゼロ補正.ps1を実行
  2. 検索対象フォルダを聞いてくるのでフォルダのフルパスを入力
  3. 変更対象のファイルがグリッド表示されるので、変更したいファイルを選択して「OK」をクリック

5. スクリプトコード

# スクリプトのウィンドウタイトルを設定します。
$host.UI.RawUI.WindowTitle = ([IO.Path]::GetFilenameWithoutExtension($PSCommandPath))

# エラー発生時の動作を設定します。
$ErrorActionPreference = 'Stop'

# スクリプトの引数をチェックし、ディレクトリパスが指定されていれば $taishoDir に設定します。
$args | Where-Object { ([IO.Directory]::Exists($_)) } | ForEach-Object { $taishoDir = $_ }

echo "------------------------------------------------------------------"
Write-Host "対象フォルダ内のファイル名の数字の部分に頭ゼロを追加して桁数を統一します" -ForegroundColor Cyan
echo "------------------------------------------------------------------"

# 対象フォルダが指定されていない、または存在しない場合に、ユーザーにフォルダの入力を促します。
while (-not ([IO.Directory]::Exists($taishoDir))) {
    $taishoDir = Read-Host "対象フォルダ"
    $taishoDir = $taishoDir.Trim('"').Trim('\')
}

Write-Host "対象フォルダ:「$($taishoDir)」" -ForegroundColor Green

Write-Progress -Activity "Searching..." -Status $taishoDir
$allFiles = @()
Set-Location -LiteralPath $taishoDir
$allDirectorys = @()
$allDirectorys += Get-Item -LiteralPath $taishoDir

# 対象フォルダ以下の全てのサブディレクトリを再帰的に取得し、$allDirectorys に追加します。
$allDirectorys += Get-ChildItem -LiteralPath $taishoDir -Recurse -Directory

# 取得した各ディレクトリ内のファイルを取得し、$allFiles に追加します。
foreach ($dicdata in $allDirectorys) {
    if ($dicdata.FullName -ne $taishoDir) {
        $allFiles += $dicdata
    }
    # 現在のディレクトリ内のファイルを取得し、$allFiles に追加します。
    $allFiles += Get-ChildItem -LiteralPath $dicdata.FullName -File
}
Write-Progress -Activity "Searching..." -Completed

$maxNumberCount = 0

$inputText = Read-Host "補正桁数を指定してください"

# ユーザーの入力が数字のみで構成されているかチェックします。
if ($inputText -match '^[0-9]+$') {
    $maxNumberCount = $inputText
} else {
    # 数字以外の入力の場合、ファイル名に含まれる最大の連続した数字の桁数を自動で取得します。
    foreach ($file in $allFiles) {
        $filename = [IO.Path]::GetFilenameWithoutExtension($file.Name)

        $numberCounter = 0
        foreach ($ch in $filename.ToCharArray()) {
            if ($ch -in ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) {
                $numberCounter += 1
            }
            else {
                $numberCounter = 0
            }

            $maxNumberCount = [Math]::Max($maxNumberCount, $numberCounter)
        }
    }
}
echo "maxNumberCount=${maxNumberCount}"

$replaceParameterList = @()

# 各ファイルの変更前後の名前を取得し、$replaceParameterList に追加します。
foreach ($file in $allFiles) {
    $oldName = [IO.Path]::GetFilenameWithoutExtension($file.Name)
    $newName = @()

    $numberBuff = @()
    # 既存のファイル名を1文字ずつループ処理します。
    foreach ($ch in $oldName.ToCharArray()) {
        # 現在の文字が数字であるかチェックします。
        if ($ch -in ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9')) {
            $numberChar = $true
            $numberBuff += $ch
        }
        else {
            $numberChar = $false
        }
        # 数字ではない文字に遭遇した場合、またはファイル名の終わりに達した場合の処理
        if ($numberChar -eq $false) {
            # 数字バッファに数字が格納されている場合
            if ($numberBuff.Count -gt 0) {
                # 最大桁数に満たない分の頭ゼロを追加します。
                for ($i = 0; $i -lt ($maxNumberCount - $numberBuff.Count); $i++) {
                    $newName += '0'
                }
                $newName += $numberBuff
                $numberBuff = @()
            }
            $newName += $ch
        }
    }
    # ファイル名の最後に数字が続く場合の処理
    if ($numberBuff.Count -gt 0) {
        # 最大桁数に満たない分の頭ゼロを追加します。
        for ($i = 0; $i -lt ($maxNumberCount - $numberBuff.Count); $i++) {
            $newName += '0'
        }
        # 数字バッファの内容を新しいファイル名に追加します。
        $newName += $numberBuff
    }

    # 新しいファイル名配列を結合し、元のファイルの拡張子を付加します。
    $newName = ($newName -join '') + [IO.Path]::GetExtension($file.Name)

    $newParam = @{ 'directory' = $file.DirectoryName; 'oldname' = $file.Name; 'newname' = $newName }

    # 変更前と変更後のファイル名が異なる場合のみ、リストに追加します。
    if ($newParam['oldname'] -ne $newParam['newname']) {
        $replaceParameterList += $newParam
    }
}

$replaceParameterCount = ($replaceParameterList | Measure-Object).Count
if ($replaceParameterCount -eq 0) {
    Write-Host "名前変更対象が見つかりませんでした。" -ForegroundColor Yellow
}

# 変更対象のファイルリストをグリッドビューで表示し、ユーザーに選択を促します。
$selectItems = $replaceParameterList | ForEach-Object { New-Object PSCustomObject -Property $_ } | Select-Object 'directory', 'oldname', 'newname' | Out-GridView -Title '変更する対象を選択してください' -PassThru
$selectCount = ($selectItems | Measure-Object).Count
Write-Host "$($selectCount)個のアイテムを選択しました" -ForegroundColor Cyan

if ($selectItems -eq $null) {
    return
}

# 選択された各アイテムに対してファイル名の変更処理を実行します。
foreach ($param in $selectItems) {
    $oldFilepath = Join-Path $param.directory $param.oldname
    $newname = $param.newname

    @("「", "White"), @($oldFilepath, "Cyan"), @("」→「", "White"), @($newname, "Green"), @("」", "White") | ForEach-Object { Write-Host $_[0] -NoNewline -ForegroundColor $_[1] }; Write-Host ''
    Rename-Item -LiteralPath $oldFilepath -NewName $newname
}

pause

6. 注意事項と既知の問題

制約事項
大量のファイルを処理する場合、完了までに時間がかかる可能性があります。

既知のバグ
もしバグを発見された場合は、コメントでご報告ください。

トラブルシューティング
・ps1ファイルのエンコーディングには注意してください。

7. 免責事項

本スクリプトにはいかなる保証もありません。使用は自己責任で行ってください。

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?