Windowsのコマンドプロンプトでは、ren でファイル名を変更できます。拡張子をまとめて変えるような処理は簡潔に書けますが、任意の文字列置換、日付追加、連番付けにはPowerShellで変更予定を作って確認する方法が分かりやすくなります。
一括リネームは元の名前を失う操作で、途中で失敗しても全体が自動で元に戻るとは限りません。まずフォルダーのコピーで試し、対象一覧と旧名・新名の対応を保存します。この記事のコードはWindowsの実機実行結果ではなく、公式構文に基づく例です。
最初に作業フォルダーとシェルを確認する
前半は cmd.exe(コマンドプロンプト)用、後半は PowerShell用です。同じWindows Terminal内でもタブによってシェルが違います。PowerShellの ren は別のコマンドの別名として解釈されるため、cmdのワイルドカード例をそのまま混ぜないでください。
以下の C:\RenameTest は、練習用コピーを置いたフォルダーの例です。実在する自分の作業場所へ変更します。ドライブ直下や業務フォルダー全体を対象にしないでください。
cd /d "C:\RenameTest"
cd
dir /b /a-d "*.txt"
最後のコマンドは対象候補を表示するだけです。隠しファイルなどの属性も含め、実際に変更してよい範囲を確認します。アプリや共有リンクがファイル名に依存している場合は、変更後に参照が切れることもあります。
基本:単一ファイルの名前を変える
ren "document1.txt" "document2.txt"
空白を含む名前も扱えるように引用符で囲みます。第1引数には元ファイルのパスを指定できますが、第2引数は同じフォルダー内の新しい名前です。別フォルダーや別ドライブへ移動するコマンドではありません。変更先の名前が存在する場合はエラーになります。
拡張子をまとめて変える

ren "*.txt" "*.bak"
現在のフォルダーで一致するファイルの拡張子を変更する例です。サブフォルダーは対象になりません。拡張子を変えてもファイルの中身や形式は変換されず、バックアップコピーも作られません。同名の .bak がある場合などは失敗し、一部だけ変更済みになることがあります。
ren の変更先ワイルドカードは、一般的な文字列置換や正規表現のキャプチャではありません。例えば ren report*.txt summary*.txt を「reportをsummaryに置換し、後ろの番号を必ず保持する」方法として使わないでください。任意の接頭辞置換は後半のPowerShell例で新しい名前を明示します。
サブフォルダーを含める場合のcmd構文
for /r は再帰的に対象を探すため、操作範囲が広がります。まず次の echo 付きで変更予定のコマンドを表示し、バックアップと衝突を確認してください。これはcmdへ直接入力する形式です。
for /r "C:\RenameTest" %F in (*.txt) do @echo ren "%~fF" "%~nF.bak"
%~fF は元ファイルのフルパス、%~nF は拡張子を除いた名前です。実行する場合は確認後に echo だけを外します。表示だけでは権限や名前衝突を完全に検証できません。特殊な文字を含む実ファイルでの動作はコピーで確認し、複雑な条件はPowerShellの計画方式を使います。
.bat/.cmd ファイルに保存する場合は、for変数の %F を %%F にします。例は次のとおりで、こちらも表示のみです。
for /r "C:\RenameTest" %%F in (*.txt) do @echo ren "%%~fF" "%%~nF.bak"
名前に example があるファイルへ接頭辞を追加する場合の構文確認例です。変更先にフルパスを埋め込む "new_%F" ではなく、名前部分の %~nxF を使います。
for /r "C:\RenameTest" %F in (*example*.txt) do @echo ren "%~fF" "new_%~nxF"
この接頭辞追加は、繰り返せば new_new_... になる可能性があります。対象を固定し、結果を確認せず再実行しないでください。遅延環境変数展開を有効にしたcmdでは、名前中の ! の扱いにも注意が必要です。
PowerShellで接頭辞を置換する:変更計画を作る

以下はPowerShellに入力します。まずファイルの一覧を配列に固定し、新しい名前を計算するだけで、まだリネームしません。例では report1.txt を summary1.txt、report2.txt を summary2.txt にする計画を作ります。
$root = 'C:\RenameTest'
$files = @(Get-ChildItem -LiteralPath $root -File -Filter 'report*.txt' |
Sort-Object Name)
$plan = @($files | ForEach-Object {
[pscustomobject]@{
OldPath = $_.FullName
NewName = $_.Name -replace '^report', 'summary'
}
})
$plan | Format-Table -AutoSize
^report は名前の先頭だけを対象にする正規表現です。-File でフォルダーを除外し、-LiteralPath で元パスの角括弧などをワイルドカードとして解釈させないようにします。この例は直下のファイルだけで、サブフォルダーは処理しません。
衝突を調べ、WhatIfで確認してから実行する
上の $plan を作成した同じPowerShellで、次の確認を行います。変更先がすでにある場合と、複数の元ファイルが同じ変更先になる場合は、処理を止めます。入れ替えリネームや大文字・小文字だけの変更も、この単純な方式では扱いません。
if ($plan.Count -eq 0) { throw '対象ファイルがありません。' }
$targets = @($plan | ForEach-Object {
Join-Path ([System.IO.Path]::GetDirectoryName($_.OldPath)) $_.NewName
})
if (@($targets | Group-Object | Where-Object Count -gt 1).Count -gt 0) {
throw '変更先が重複しています。'
}
foreach ($target in $targets) {
if (Test-Path -LiteralPath $target) {
throw "変更先が既にあります: $target"
}
}
$plan | Export-Csv -LiteralPath (Join-Path $root 'rename-plan.csv') `
-NoTypeInformation -Encoding UTF8 -NoClobber
foreach ($item in $plan) {
Rename-Item -LiteralPath $item.OldPath -NewName $item.NewName -WhatIf
}
rename-plan.csv は旧パスと新名の対応表です。-NoClobber により既存の対応表を上書きしないので、既にある場合は別名で保存します。-WhatIf は実際には名前を変えませんが、実行時のロックや権限、後から発生する競合まで保証するものではありません。
表示とバックアップを確認できた場合にだけ、次を実行します。エラー時は停止しますが、すでに成功した変更まで巻き戻されるわけではありません。同期ソフトや他の利用者による同時変更がない状態で行います。
foreach ($item in $plan) {
Rename-Item -LiteralPath $item.OldPath -NewName $item.NewName -ErrorAction Stop
}
失敗したら、対応表と現在のファイル名を照合して変更済み・未変更を分けます。自動で逆方向に一括実行すると別ファイルとの衝突を起こす可能性があるため、対応表は復旧判断の資料として使い、確認せず繰り返さないでください。
連番・日付・条件付きリネームの作り方
次の例はいずれも、上の $plan を作る部分の代替です。一つだけ選んで計画を作り、同じ衝突確認と -WhatIf に進みます。実行ブロックまでまとめて貼り付けないでください。
連番:名前順に並べ、item_0001.txt から付けます。名前順は自然な数値順やエクスプローラーの表示順と同じとは限らないため、対応表を確認します。
$files = @(Get-ChildItem -LiteralPath $root -File -Filter '*.txt' | Sort-Object Name)
$i = 0
$plan = @($files | ForEach-Object {
$i++
[pscustomobject]@{
OldPath = $_.FullName
NewName = ('item_{0:D4}{1}' -f $i, $_.Extension)
}
})
$plan | Format-Table -AutoSize
日付:cmdの %date% を固定位置で切り出す方法は地域設定に依存します。PowerShellで形式を指定して、今回の処理開始時の日付を一度だけ取得します。ファイルの更新日ではありません。
$stamp = Get-Date -Format 'yyyyMMdd'
$files = @(Get-ChildItem -LiteralPath $root -File -Filter '*.txt')
$plan = @($files | ForEach-Object {
[pscustomobject]@{ OldPath = $_.FullName; NewName = $stamp + '_' + $_.Name }
})
$plan | Format-Table -AutoSize
10日前より古い更新日時:比較の基準時刻を固定し、すでに old_ の付いたファイルを除外します。これは作成日ではなく最終書き込み日時で、ちょうど境界の時刻は含みません。
$cutoff = (Get-Date).AddDays(-10)
$files = @(Get-ChildItem -LiteralPath $root -File -Filter '*.txt' |
Where-Object { $_.LastWriteTime -lt $cutoff -and $_.Name -notlike 'old_*' })
$plan = @($files | ForEach-Object {
[pscustomobject]@{ OldPath = $_.FullName; NewName = 'old_' + $_.Name }
})
$plan | Format-Table -AutoSize
本文に「重要」があるファイル:次はUTF-8のテキストを想定します。文字コードが違う場合は、使っているPowerShellが対応する正しい文字コードに変更してください。-SimpleMatch は文字列として検索し、-Quiet は一致の有無を返します。
$files = @(Get-ChildItem -LiteralPath $root -File -Filter '*.txt' |
Where-Object { $_.Name -notlike 'important_*' } |
Where-Object {
Select-String -LiteralPath $_.FullName -Pattern '重要' `
-SimpleMatch -Quiet -Encoding UTF8 -ErrorAction Stop
})
$plan = @($files | ForEach-Object {
[pscustomobject]@{ OldPath = $_.FullName; NewName = 'important_' + $_.Name }
})
$plan | Format-Table -AutoSize
よくあるエラーと対処法

アクセス拒否:ファイルを使用中のアプリ、読み取り専用属性、共有・NTFSの権限、同期状態を確認します。必要な権限は所有者・管理者に相談し、いきなり管理者実行やアクセス権の全面変更で対応しません。
見つからない:現在のフォルダー、拡張子の表示、フィルター、すでに変更済みでないかを確認します。名前重複:既存ファイルや変更予定の重複を確認します。構文エラー:cmdとPowerShellの混在、cmd直入力の %F とバッチの %%F、引用符、変更先にパスを書いていないかを確認します。
管理者権限や実行ポリシーの緩和は、一般のリネームに一律必要なものではありません。予約名、禁止文字、長いパスなどの制約もあるため、複雑な名前を含むデータは必ずコピーで検証してください。
まとめ・公式リファレンス
単純な拡張子変更はcmdの ren、接頭辞置換や連番・日付・本文条件はPowerShellで計画を作る方法が適しています。対象を固定し、衝突確認、対応表、プレビュー、バックアップを揃えてから実行します。ここに示したコードのWindows/PowerShell実行試験は行っていません。



コメント