MRが楽しい

MRやVRについて学習したことを書き残す

PowerShellでフォルダ内のファイル名に生成日時のタイムスタンプを一括追加する

本日はPowerShellの小ネタ枠です。
PowerShellでフォルダ内のファイル名に生成日時のタイムスタンプを一括追加する方法です。

フォルダ内のファイルを一括取得する

Get-ChildItem関数を利用すると指定のフォルダ内のファイルやフォルダを取得できます。
パラメータを指定することで取得対象をファイルまたはフォルダに絞ることも可能です。
learn.microsoft.com

// 指定パス配下にあるディレクトリの一覧を取得する
Get-ChildItem -Path C:\Test -Directory

ファイル名の生成日時を取得する

Get-ItemPropertyは指定したファイルやフォルダのプロパティを取得します。
learn.microsoft.com

Get-ItemProperty C:\Windows

以下のようにプロパティ名を指定することで特定の情報を参照できます。
作成日時は CreationTime、更新日時は LastWriteTime で取得できます。

(Get-ItemProperty C:\Windows).CreationTime
(Get-ItemProperty C:\Windows).LastWriteTime

また取得した日時情報は以下のようにフォーマットを指定して文字列で出力することができます。

(Get-ItemProperty C:\Windows).CreationTime.ToString("yyyyMMddHHmmss")

サンプルスクリプト

指定フォルダのパスを引数で受け取り、指定フォルダ内のファイルまたはフォルダ名のファイル名に更新日時のタイムスタンプを追加する以下のサンプルスクリプトを作成しました。

# 1つ目の引数を要求する
# 引数を指定していなかった場合は対話形式で入力を要求する
Param(
	[parameter(mandatory)][String]$argment01
)

# 指定されたディレクトリが存在するか確認
if (-not (Test-Path $argment01 -PathType Container)) {
    Write-Host "Error:The specified directory does not exist."
    exit
}

# 受け取った引数を変更対象のディレクトリとして指定する
$targetDirectory = $argment01

# 実行メッセージを表示する
Write-Host ("Target Directory is " + $targetDirectory)

# ディレクトリ内のフォルダを取得
$items = Get-ChildItem -Path $targetDirectory

# マッチングするフォルダの確認フラグ
$matchFound = $false
foreach ($item in $items) {
    # フォルダの更新日時を取得
    $creationTime = $item.LastWriteTime

    # タイムスタンプを YYYYMMDDHHmmSS 形式に変換
    $timestamp = $creationTime.ToString("yyyyMMddHHmmss")

    # すでにタイムスタンプがついている場合はスキップ
    if ($item.Name -match "^\d{14}_") {
        Write-Output "Skipped: $($item.Name) is already time-stamped."
        continue
    }

    # ファイルとフォルダで処理を分岐
    if ($item.PSIsContainer) {
        # フォルダの場合
        $newName = "$timestamp`_$($item.Name)"
        $oldPath = $item.FullName
        $newPath = Join-Path $item.Parent.FullName $newName
    } else {
        # ファイルの場合
        $baseName = $item.BaseName
        $extension = $item.Extension
        $newName = "$timestamp`_$baseName$extension"
        $oldPath = $item.FullName
        $newPath = Join-Path $item.DirectoryName $newName
    }
    
    if (-not (Test-Path $newPath)) {
        Rename-Item -Path $oldPath -NewName $newName
        Write-Output "Renamed: $($item.Name) -> $newName"
        $matchFound = $true
    } else {
        Write-Output "Skipped: $newName already exists"
    }
}

# フォーマットが一致するフォルダがなかった場合はメッセージを表示する
if (-not $matchFound) {
    Write-Output "No corresponding folder was found."
}

以下の通りファイルまたはフォルダが存在する対象のパスを指定して実行してみます。

結果全てのファイルとフォルダの名前に更新日時のタイムスタンプを追加できました。