🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

コマンドプロンプト

コマンドプロンプト(cmd.exe)はMicrosoftによって提供されているコマンドラインインタプリタです。OS/2・Windows CE・Windows NTで使用可能です。

Q&A

解決済

2回答

31627閲覧

ファイル名の一部を一括変更

退会済みユーザー

退会済みユーザー

総合スコア0

Windows

Windowsは、マイクロソフト社が開発したオペレーティングシステムです。当初は、MS-DOSに変わるOSとして開発されました。 GUIを採用し、主にインテル系のCPUを搭載したコンピューターで動作します。Windows系OSのシェアは、90%を超えるといわれています。 パソコン用以外に、POSシステムやスマートフォンなどの携帯端末用、サーバ用のOSもあります。

PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

コマンドプロンプト

コマンドプロンプト(cmd.exe)はMicrosoftによって提供されているコマンドラインインタプリタです。OS/2・Windows CE・Windows NTで使用可能です。

1グッド

1クリップ

投稿2019/12/14 03:14

編集2019/12/24 14:47

前提・実現したいこと

コマンドプロンプトやPowerShell等、Windows標準機能の中で、下記のように複数ファイルのファイル名の一部を一括変更したいのですが、どのようにすればよいでしょうか?
ご教示お願いします。

現在のディレクトリから、最下層のファイルまで、ファイル名の中の[test1]の文字列を[test]に変更したいと思っています。 ファイル名のaaaやbbbやcccの文字やディレクトリのdddやgggの名前等は任意です。 ファイル数やディレクトリ数やディレクトリの階層数も任意です。 //置換前。 │ aaa[test1].txt │ bbb[test1].txt │ ccc[test1].txt │ └─ddd │ eee[test1].txt │ fff[test1].txt │ └─ggg hhh[test1].txt //置換後。 │ aaa[test].txt │ bbb[test].txt │ ccc[test].txt │ └─ddd │ eee[test].txt │ fff[test].txt │ └─ggg hhh[test].txt

試したこと

コマンドプロンプト

>ren *[test1].txt *[test].txt

現在の階層のファイルのみが名前変更されました。
最下層のサブフォルダまで一括で変更する方法はありませんか?
もしくは、ディレクトリは別コマンドで変更するとして、ファイルだけでも最下層まで一括で変更する方法はありませんか?

補足情報(FW/ツールのバージョンなど)

Windows 10

### 追記

@echo off ren *[test1].txt *[test].txt for /r /d %%A in (*) do ( pushd %%A ren *[test1].txt *[test].txt popd ) for /r /d %%B in (*[test1]) do call :rename %%B exit/b :rename set A=%1 ren %A% %A:[test1]=[test]% exit/b pause

### 追記②

pauseを打って、処理の経過を調べてみました。

@echo off ren *[test1].txt *[test].txt for /r /d %%A in (*) do ( pushd %%A ren *[test1].txt *[test].txt popd ) pause for /r /d %%B in (*[test1]) do call :rename %%B pause exit /b :rename set A=%1 echo %A% rem ren %A% %A:[test1]=[test]% ←ここをコメントアウトするかしないかでエラーメッセージの出る出ないが変わる。 exit /b

コメントアウトしなかった場合、echo %A%の後に下記エラーが出力される。
コメントアウトした場合はエラーメッセージが出力されない。

コマンドの構文が誤っています。

### 追記③

ren %A% %A:[test1]=[test]%

上記がフォルダ名の一部変更ができる書き方かと思うのですが、コードが理解できていないため、
質問1と質問2があります。
「フォルダ 名前 一部変更 ren」などで検索してるのですが、なかなか情報が出てきませんでした。

質問1。
追記②のrenをmoveに変えて、意図した処理はできました。
ただ、追記②のrenをmoveに変えた書き方ならば、サブルーチンで書かない方法でもできるのではないかと思ったのですが、コードの書き換えができませんでした。
下記のように試したりしました。

@echo off ren *[test1].txt *[test].txt for /r /d %%A in (*) do ( pushd %%A ren *[test1].txt *[test].txt popd ) for /r /d %%B in (*[test1]) do call :rename %%B move %B% %B:[test1]=[test]% exit /b

質問2。
最上位階層ではどのようにすればフォルダ名の一部変更ができますか?

@echo off ren *[test1].txt *[test].txt rem 最上位階層ではどうすればフォルダ名の一部を変更できますか? ren *[test1] *[test] ←これではフォルダ名は変更できない。 for /r /d %%A in (*) do ( pushd %%A ren *[test1].txt *[test].txt for /d %%B in (*[test1]) do call :rename %%B exit /b popd ) :rename set A=%1 echo %A% ren %A% %A:[test1]=[test]% exit /b

### 追記④

質問1
サブルーチンを書かない方法を試しているのですが、意図した処理になりませんでした。

@echo off ren *[test1].txt *[test].txt for /r /d %%A in (*) do ( pushd %%A ren *[test1].txt *[test].txt popd ) for /r /d %%B in (*[test1]) do ( move %%B %%B:[test1]=[test]%% )

コードを理解していないので、下記なども試してみました。

move %B %%B:[test1]=[test]% move %%B %%B:[test1]=[test]%% move %%B %B:[test1]=[test]%

質問2
サブルーチンを書く方は、

@echo off ren *[test1].txt *[test].txt for /d %%B in (*[test1]) do call :rename %%B for /r /d %%A in (*) do ( pushd %%A ren *[test1].txt *[test].txt for /d %%B in (*[test1]) do call :rename %%B exit /b popd ) :rename set A=%1 echo %A% ren %A% %A:[test1]=[test]% exit /b

フォルダ直下と、その下のサブフォルダまでは名前変更できたのですが、
そのさらに下のサブフォルダの階層は、ファイルもフォルダも名前変更されませんでした。

DrqYuto👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

for /r /dで、全ディレクトリに対して括弧内を実行します。
カレントディレクトリだけは別途実行。

CMD

1ren *[test1].txt *[test].txt 2for /r /d %%A in (*) do ( 3 pushd %%A 4 ren *[test1].txt *[test].txt 5 popd 6)

対象のファイルが無いディレクトリがもしあれば、そこではrenがエラーになりますが、気にしないことにします。

投稿2019/12/14 15:15

otn

総合スコア85893

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/12/21 17:02

ご回答ありがとうございます。 理解するのに時間がかかり、コメントが遅くなってしまいました、申し訳ありません。 なぜ、pushdが必要なのかわからなかったのですが、%%Aはディレクトリを取得するだけで、そこに移動まではしていないということだったのですね? そこで、pushdで実際にそこに移動しているかどうか確かめてみたかったのですが、 下記のようにしたらうまくいきませんでした。echo %CD%は、バッチファイルの場所を取得してしまうのでしょうか? pushd %%A で移動したときのディレクトリを出力する方法があれば教えていただけませんか? for /r /d %%A in (*) do ( pushd %%A echo %CD% popd ) pause
otn

2019/12/22 00:01

%CD%のような環境変数は、for文を開始する時点で展開されるので、for文を実行する前のディレクトリになります。 cd と書けば、その時のディレクトリを表示します。
退会済みユーザー

退会済みユーザー

2019/12/22 07:40 編集

ご回答ありがとうございます。 cdと書いて確認できました、ありがとうございます。 すみません、調べるうちに気になる点が2点ありました。 ご教示お願いします。 質問1。 さらに気づいたのですが、今回の意図したい処理ならば、下記のようにcdに書き直しても、問題ないですか? ren *[test1].txt *[test].txt for /r /d %%A in (*) do ( cd %%A ren *[test1].txt *[test].txt ) cd %%Aの移動で書いた場合と、pushd %%Aとpopdの移動で書いた場合の違いは、 for文で回し終わった後に、for文を実行する前の元のカレントディレクトリに戻っているかどうかの違いという認識で合っていますか? 質問2。 あと、ディレクトリに対しても、例えば「dir1[test1]」という名前のディレクトリを「dir1[test]」のように置換したく、下記のように試してみたのですが、置換されなかったのは何故でしょうか? どのようにすればディレクトリも置換できますか?  @echo off ren *[test1].txt *[test].txt ren *[test1] *[test] ←ディレクトリの置換を試みている。 for /r /d %%A in (*) do ( pushd %%A ren *[test].txt *[test1].txt ren *[test1] *[test]  ←ディレクトリの置換を試みている。 popd ) pause
otn

2019/12/22 10:52

質問1:それでもOKです。pushd/popdのほうが「一時的に変更」のニュアンスが出る程度と、最後に戻っているかどうかですね。他に細かい違いというと、ドライブが異なる場合はcdでは移動できないのでcd /dと書きます。 質問2:renやmoveに、* を使うと、ディレクトリにはマッチしないですね。個別にリネームするしかない for /d %%B in (*[test1]) do call :rename %%B ~~~ exit/b :rename set A=%1 ren %A% %A:[test1]=[test]% exit /b
退会済みユーザー

退会済みユーザー

2019/12/22 12:42

ご回答ありがとうございます。 質問1のご回答ありがとうございます。理解できました。 質問2なのですが、再帰的に最下層のディレクトリの範囲までリネームしたく、 質問の追記のコードで実行したのですが、サブフォルダ以降はリネームが効かなかったのですが、どのようにすれば、再帰的に反映させることができますか? exit/bで処理が停止してしまっているのかもしれませんが、これを書かないと、次の行の:renameとの境界にならないのかなと解釈しています。
otn

2019/12/22 12:48

ディレクトリによって効く効かないは無いので、どこか間違っているんだと思います。 いままで、バッチスクリプト内のサブルーチンを書いたことありますか?
退会済みユーザー

退会済みユーザー

2019/12/22 14:33

ご回答ありがとうございます。 バッチスクリプト内のサブルーチンは初めてです。 検索して、書式みたいなものは理解したつもりですが、確かではないかもしれません。 ren %A% %A:[test1]=[test]% このコードを理解していないのですが、この辺りで不具合が起こる可能性はありますか? このコードをコメントアウトするとエラーメッセージが表示されなくなりました。 詳細は、質問の追記②に記述しました。
otn

2019/12/22 14:52

ああ、そう書いたのですね。 ren *[test1].txt *[test].txt のとなりに、 for /d %%B in (*[test1]) do call :rename %%B を入れるつもりで書いています。なので、/r は入れていません。 上位のディレクトリで /r すると、ディレクトリ名が付いちゃうので、 ren D:\path\dir\XXX[test1] D:\path\dir\XXX[test] みたいになり、エラーです。新名称にディレクトリはつけられません。 そのままの位置だと、move にかえるといいと思います。
退会済みユーザー

退会済みユーザー

2019/12/23 17:16

ご回答ありがとうございます。 追記②のrenをmoveに変える書き方で意図した処理はできました。 また、前者の方も、となりに書いて、回してる階層のフォルダ変更は処理が通りました。 ただ、前者の場合、最上位階層でフォルダ変更する方法がわからず、 また、moveの方の書き方に関しても、サブルーチンで書かなくてもまとめられるのではと思って試したのですが、それもうまくいかずで、申し訳ないですが、2点質問があります。 詳細は追記③に記述しました。
otn

2019/12/24 05:02

> サブルーチンで書かない方法でもできるのではないか call :renameというサブルーチンコールが入っていて、呼ばれる:renameがありませんが? > 最上位階層ではどのようにすればフォルダ名の一部変更ができますか? 先頭で、 for /d %%B in (*[test1]) do call :rename %%B です。
退会済みユーザー

退会済みユーザー

2019/12/24 14:48

ご回答ありがとうございます。 サブルーチンの呼び出しを削除するのを忘れていました。ご指摘ありがとうございます。 ただ、削除してサブルーチンを書かない方法を試してみましたが、やはりできませんでした。 また、サブルーチンを呼び出すほうですが、 先頭で、 for /d %%B in (*[test1]) do call :rename %%B としたところ、フォルダ直下と、その下のサブフォルダまでは名前変更できたのですが、 そのさらに下のサブフォルダの階層はファイルもフォルダも名前変更されていませんでした。 詳細は追記④に記述しました。
otn

2019/12/24 15:27

質問1: Forの制御変数と、環境変数は全く異なるものです。 %A:[test1]=[test]% のような文字列置換は、環境変数のみの機能です。 質問2: ループの途中で、 exit /b しているからですね。意味不明です。
退会済みユーザー

退会済みユーザー

2019/12/25 16:48

ご回答ありがとうございます。 質問2について。 exit /bをよく理解していませんでした。修正したら意図通りに処理が通りました。ありがとうございます。 質問1について。 Forの制御変数を環境変数に入れれば、置換できるかもしれないと思い試したのですが、意図通りの処理にならず、環境変数にセットしている時点でechoしたら、何も出力されなかったのですが、 下記のようなことでは置換はできませんか?修正可能でしたら、ご教示いただけませんか? for /r /d %%B in (*[test1]) do ( set dir = %%B echo %dir% pause move %dir% %dir:[test1]=[test]% )
otn

2019/12/26 00:22 編集

まず、 set dir = %%B と set dir=%%B は働きが異なりますので、注意してください。CMD:EXEは空白が意味を持つ言語です。 set dir = ABC は、「dir空白」という環境変数に、「空白ABC」をセットします。 他の多くのプログラミング言語と異なり、環境変数名には空白や(一部を除き)記号が使えます。 また、for文の繰り返しの文の中での環境変数のセットと参照については、この書き方では出来ませんので、set /? を参照してください。遅延環境変数を使います。
退会済みユーザー

退会済みユーザー

2019/12/26 14:58

ご回答ありがとうございます。 空白が意味を持つのですね。勉強になります。 遅延環境変数で調べたところ、意図した処理ができるようになりました。 ご教示いただき、ありがとうございました。
guest

0

こちらのサイトの解説が分かりやすそうです。

フォルダ内のファイルを再帰的にリネームするバッチファイルの書き方
http://xn--u9j0md1592aqmt715c.net/how-to-write-recursive-bat/

投稿2019/12/14 07:15

segavvy

総合スコア1038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/12/26 14:58

ご回答ありがとうございした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問