課題
前回そして前々回とファイル/フォルダ名を変換するバッチファイルを作成した記事を投稿した。
人の欲望とは恐ろしいもので,これまで手作業でチマチマとファイル名を変えていたのがバッチファイルによって一発変更できるようになるといろいろと欲(改善要求)が出てくるのだ。その中でも最大の意見は「ファイル(またはフォルダ)を再帰的に検索できるようにしたい」というものである。
方法その1
別に新たなツールを作らなくても良い。Windows には ForFiles
コマンドというコマンドがあり,それを使えば十分用が足せるのだ。具体的なコマンドライン指定は以下のようになる。なおユーザの環境によっては ucase.cmd
は絶対パスで与える必要があるかもしれない。
forfiles /S /P 検索フォルダ /M 検索パターン /C "cmd /c ucase.cmd @path"
ただ,実際に試してみると,この ForFiles
コマンドはクッソ遅いのだ。
なぜこんなに遅いのか原因は不明だが,非常に高機能であることから,内部的に何らかの中間言語を生成してインタプリター実行しているのではないかと推察している。
方法その2
特定のディレクトリ以下のファイル/フォルダを再帰的に検索したい。この場合,一番高速かつ手軽な方法は dir
コマンドの出力を利用することである。検索パスにはワイルドカードが含まれてもよいし,複数のパスを羅列することもできる。フォルダを対象とするときはオプション /ad
を付ける必要があり,逆にファイルのみを対象にする(フォルダを対象にしない)ときはオプション /a-d
を付ける。
for /F "usebackq tokens=*" %%I in ( `dir /s /b /a-d 検索パス ...` ) do call :CONVERT "%%~I"
for /F "usebackq tokens=*" %%I in ( `dir /s /b /ad 検索パス ...` ) do call :CONVERT "%%~I"
なお,検索パスにマッチしなかった場合「ファイルが見つかりません」というエラーメッセージが出力されるので,それが気に入らない人は標準エラー出力を NUL
デバイスにリダイレクトすればよい。
実装コードを以下に示す。
UCASE2.CMD のソースコードハコチラ
@echo off
rem ------------------------------------------------------------------------
rem ファイル名(複数可)を大文字に変換する
rem ------------------------------------------------------------------------
setlocal enabledelayedexpansion
set ROPT=0
set DOPT=0
set QOPT=0
set VOPT=0
set COUNT=0
rem ------------------------------------------------------------------------
rem オプション解析
rem ------------------------------------------------------------------------
set ARGS=
if "%~1"=="" goto USAGE
:LOOP
set OPT=%~1
if /I "%OPT%"=="/R" set ROPT=1&&goto ENDIF
if /I "%OPT%"=="/D" set DOPT=1&&goto ENDIF
if /I "%OPT%"=="/Q" set QOPT=1&&goto ENDIF
if /I "%OPT%"=="/V" set VOPT=1&&goto ENDIF
if "%OPT:~0,1%"=="/" goto ERROR
if defined ARGS (
set ARGS=%ARGS% "%~1"
) else (
set ARGS="%~1"
)
:ENDIF
shift
if "%~1"=="" goto BREAK
goto LOOP
:ERROR
echo オプション %OPT% には対応していません!
exit /b
:BREAK
if not defined ARGS (
echo ファイル名を指定して下さい!
exit /b
)
rem ------------------------------------------------------------------------
rem ファイル名/フォルダ名を変更する
rem ------------------------------------------------------------------------
set DIROPT=/b
if "%DOPT%"=="1" (
set DIROPT=%DIROPT% /ad
) else (
set DIROPT=%DIROPT% /a-d
)
if "%ROPT%"=="1" (
set DIROPT=/s %DIROPT%
)
for /F "usebackq tokens=*" %%I in ( `dir %DIROPT% %ARGS% 2^>NUL` ) do (
call :CONVERT "%%~I"
)
if "%VOPT%"=="1" (
echo %COUNT% 個のファイル名を変更します。
) else (
echo %COUNT% 個のファイル名を変更しました。
)
exit /b
rem ------------------------------------------------------------------------
rem ファイル名/フォルダ名を変更する
rem ------------------------------------------------------------------------
:CONVERT
set OLDNAME=%~nx1
set NEWNAME=%OLDNAME%
for %%C in ( A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ) do (
set "NEWNAME=!NEWNAME:%%C=%%C!"
)
if "%OLDNAME%"=="%NEWNAME%" exit /b
if "%QOPT%"=="0" echo %~1 %NEWNAME%
if "%VOPT%"=="0" ren "%~1" "%NEWNAME%"
set /a COUNT=COUNT+1
exit /b
rem ------------------------------------------------------------------------
rem ヘルプメッセージ
rem ------------------------------------------------------------------------
:USAGE
echo ファイル名(複数可)を大文字に変更します。
echo.
echo UCASE2(.CMD) [/R] [/D] [/Q] [/V] [ドライブ:][パス][ファイル名]
echo.
echo /R ファイル/フォルダを再帰的に検索します。
echo /D フォルダ名を変更します。
echo /Q 変更したファイル名を表示しません。
echo /V 変更対象となるファイル名を表示するだけで、変更は行いません。
exit /b
ただし,上記の UCASE2.CMD
を深い階層を持つフォルダに適用すると,ファイル名の変更を開始するまで暫く待たされ,もっさりとした起動感になる。これは,Windows の場合,dir
コマンドが検索結果をいったんテンポラリファイルに出力し終えてから for /F
コマンドがこのテンポラリファイルを読み出すことにって処理が開始されるからだ。このあたり,パイプ処理が並列に実行される UNIX と異なり,Windows のまだまだ不便なところだと思う。このあたり PowerShell では改善されてはいるようだが。
方法その3
瞬時に動作を開始させたいのであれば for /R
コマンドを使ってファイルを再帰的に検索すれば良い。
for /R 検索フォルダ %%I in ( 検索パターン ) do call :CONVERT "%%~I"
for /R 検索フォルダ /D %%I in ( 検索パターン ) do call :CONVERT "%%~I"
ところが,方法その2と同様に検索パスのみを与えて,スクリプト側で検索フォルダと検索パターンに分離させようとすると,この方法は面倒な課題が続出する。
パスの分離
for /R
コマンドには検索フォルダと検索パターンの二つの引数が必要であり,たとえば c:\sample\*.doc
というパスが与えられていたとして,これをフォルダ名 c:\sample\
とベース名 *.doc
に分割する必要がある。たとえば変数 %I
に c:\sample\*.txt
というパスが与えられているとき,%~dpI
は c:\sample\
となるが,%~nxI
は *.txt
とはならず,ワイルドカードが展開されて *.txt
にマッチングするファイルの一つに変換されてしまうのだ。マッチするファイルが存在しない場合は空文字列になる。
ワイルドカード文字の変換
これを防ぐためにはパス名のワイルドカード文字 *
をいったん文字列 __WILDCARD__
に変換し,フォルダ名とベース名に分割した後に __WILDCARD__
を *
に戻せばよい。バッチファイルにおいては set
コマンドによる文字列置換機能が知られているが,実はワイルドカード文字 *
を置換することができない。何故かエスケープ文字 ^
も効かない。※詳しくは参考文献参照のこと。
set VAR=%VAR:文字列1=文字列2%
このため下記のように一文字ずつ置換していくしかない。
rem ------------------------------------------------------------------------
rem ワイルドカード文字の置換
rem * → __ASTERISK__
rem ? → __QUESTION__
rem ------------------------------------------------------------------------
:WILDCARD
setlocal
set STR=%~1
set RET=
:WILDCARD_LOOP
if "%STR%"=="" goto WILDCARD_BREAK
set CHR=%STR:~0,1%
if "%CHR%"=="*" set CHR=__ASTERISK__
if "%CHR%"=="?" set CHR=__QUESTION__
set RET=%RET%%CHR%
set STR=%STR:~1%
goto WILDCARD_LOOP
:WILDCARD_BREAK
endlocal&&set %2=%RET%
exit /b
ちなみにワイルドカード文字 ?
のほうは set
コマンドで問題なく置換できるため,上記のサブルーチンを使用しなくても良い。
for /R コマンドの課題
for /R
コマンドで与える検索パターン文字列にワイルドカード文字 *
および ?
が含まれている場合,検索パターン文字列にマッチするファイル名をリストアップしてくれる。このときリストアップしたファイルは必ず存在する。ところが,ワイルドカード文字が含まれていない場合,単に与えた検索パターン文字列を羅列するだけである。この場合,リストアップされたファイルが実在する保証はない。これを防ぐためには if exist
コマンドを用いてファイルの実在チェックを行えば良いが,実在チェックだけではファイルとフォルダの区別がつかないのでファイルの属性を得て判断せざるを得ない。
for /R 検索フォルダ %I in ( 検索パターン ) do (
set ATTR=%%~aI
if "!ATTR:~0,1!"=="-" call :CONVERT "%%~I"
)
for /R 検索フォルダ /D %I in ( 検索パターン ) do (
set ATTR=%%~aI
if "!ATTR:~0,1!"=="d" call :CONVERT "%%~I"
)
実装コード
ということで上記のテクニックを組み合わせた実装コードを以下に示す。
UCASE3.CMD のソースコードはコチラ
@echo off
setlocal enabledelayedexpansion
rem ------------------------------------------------------------------------
rem ファイル名(複数可)を大文字に変換する
rem ------------------------------------------------------------------------
set ROPT=0
set DOPT=0
set QOPT=0
set VOPT=0
set COUNT=0
rem ------------------------------------------------------------------------
rem オプション解析
rem ------------------------------------------------------------------------
set ARGS=
if "%~1"=="" goto USAGE
:LOOP
set OPT=%~1
if /I "%OPT%"=="/R" set ROPT=1&&goto ENDIF
if /I "%OPT%"=="/D" set DOPT=1&&goto ENDIF
if /I "%OPT%"=="/Q" set QOPT=1&&goto ENDIF
if /I "%OPT%"=="/V" set VOPT=1&&goto ENDIF
if "%OPT:~0,1%"=="/" goto ERROR
call :WILDCARD "%~1" STR
if defined ARGS (
set ARGS=%ARGS% "%STR%"
) else (
set ARGS="%STR%"
)
:ENDIF
shift
if "%~1"=="" goto BREAK
goto LOOP
:ERROR
echo オプション %OPT% には対応していません!
exit /b
:BREAK
call :MAIN %ARGS%
exit /b
rem ------------------------------------------------------------------------
rem ワイルドカードの置換
rem * → __ASTERISK__
rem ? → __QUESTION__
rem ------------------------------------------------------------------------
:WILDCARD
set STR=%~1
set RET=
:WILDCARD_LOOP
if "%STR%"=="" goto WILDCARD_BREAK
set C=%STR:~0,1%
if "%C%"=="*" set C=__ASTERISK__
if "%C%"=="?" set C=__QUESTION__
set RET=%RET%%C%
set STR=%STR:~1%
goto WILDCARD_LOOP
:WILDCARD_BREAK
set %2=%RET%
exit /b
rem ------------------------------------------------------------------------
rem ファイル名/フォルダ名を変更する
rem ------------------------------------------------------------------------
:MAIN
:MAIN_LOOP
if "%ROPT%"=="1" (
set RFLAG=/R %~dp1
set PATTERN=%~nx1
) else (
set RFLAG=
set PATTERN=%~1
)
set PATTERN=%PATTERN:__ASTERISK__=*%
set PATTERN=%PATTERN:__QUESTION__=?%
if "%DOPT%"=="1" (
for %RFLAG% /D %%I in ( %PATTERN% ) do (
set ATTR=%%~aI
if "!ATTR:~0,1!"=="d" call :CONVERT "%%~I"
)
) else (
for %RFLAG% %%I in ( %PATTERN% ) do (
set ATTR=%%~aI
if "!ATTR:~0,1!"=="-" call :CONVERT "%%~I"
)
)
shift
if "%~1"=="" goto MAIN_BREAK
goto :MAIN_LOOP
:MAIN_BREAK
if "%VOPT%"=="1" (
echo %COUNT% 個のファイル名を変更します。
) else (
echo %COUNT% 個のファイル名を変更しました。
)
exit /b
rem ------------------------------------------------------------------------
rem ファイル名/フォルダ名を変更する
rem ------------------------------------------------------------------------
:CONVERT
set OLDNAME=%~nx1
set NEWNAME=%OLDNAME%
for %%C in ( A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ) do (
set "NEWNAME=!NEWNAME:%%C=%%C!"
)
if "%OLDNAME%"=="%NEWNAME%" exit /b
if "%QOPT%"=="0" echo %~1 %NEWNAME%
if "%VOPT%"=="0" ren "%~1" "%NEWNAME%"
set /a COUNT=COUNT+1
exit /b
rem ------------------------------------------------------------------------
rem ヘルプメッセージ
rem ------------------------------------------------------------------------
:USAGE
echo ファイル名(複数可)を大文字に変更します。
echo.
echo UCASE3(.CMD) [/R] [/D] [/Q] [/V] [ドライブ:][パス][ファイル名] ...
echo.
echo /R ファイル/フォルダを再帰的に検索します。
echo /D フォルダ名を変更します。
echo /Q 変更したファイル名を表示しません。
echo /V 変更対象となるファイル名を表示するだけで、変更は行いません。
exit /b
実行結果の比較
とあるフォルダ以下にある合計 4672 個のファイル名の変更を行った際の実行時間の比較である。ForFiles
コマンドはすごく遅いことが分かり,今後,大量のファイルを扱うときは躊躇してしまう結果となった。圧倒的に最速なのは dir
コマンドの出力を用いる UCASE2.CMD
である。初動はワンテンポ遅れるが,その後の動作は流れるように速い。苦労して作った UCASE3.CMD
は初動こそレスポンス良いものの,その後はまったりと動き,意外に奮わない結果となった。
おまけ
同様にして大文字を小文字に変換するバッチファイル LCASE2.CMD
も簡単に作ることができる。サブルーチン CONVERT
を差し替えるだけで良い。当然のことながら dir
コマンドの出力を用いる UCASE2.CMD
がベースである。
LCASE2.CMD のソースコードはコチラ
@echo off
rem ------------------------------------------------------------------------
rem ファイル名(複数可)を小文字に変換する
rem ------------------------------------------------------------------------
setlocal enabledelayedexpansion
set ROPT=0
set DOPT=0
set QOPT=0
set VOPT=0
set COUNT=0
rem ------------------------------------------------------------------------
rem オプション解析
rem ------------------------------------------------------------------------
set ARGS=
if "%~1"=="" goto USAGE
:LOOP
set OPT=%~1
if /I "%OPT%"=="/R" set ROPT=1&&goto ENDIF
if /I "%OPT%"=="/D" set DOPT=1&&goto ENDIF
if /I "%OPT%"=="/Q" set QOPT=1&&goto ENDIF
if /I "%OPT%"=="/V" set VOPT=1&&goto ENDIF
if "%OPT:~0,1%"=="/" goto ERROR
if defined ARGS (
set ARGS=%ARGS% "%~1"
) else (
set ARGS="%~1"
)
:ENDIF
shift
if "%~1"=="" goto BREAK
goto LOOP
:ERROR
echo オプション %OPT% には対応していません!
exit /b
:BREAK
if not defined ARGS (
echo ファイル名を指定して下さい!
exit /b
)
rem ------------------------------------------------------------------------
rem ファイル名/フォルダ名を変更する
rem ------------------------------------------------------------------------
set DIROPT=/b
if "%DOPT%"=="1" (
set DIROPT=%DIROPT% /ad
) else (
set DIROPT=%DIROPT% /a-d
)
if "%ROPT%"=="1" (
set DIROPT=/s %DIROPT%
)
for /F "usebackq tokens=*" %%I in ( `dir %DIROPT% %ARGS% 2^>NUL` ) do (
call :CONVERT "%%~I"
)
if "%VOPT%"=="1" (
echo %COUNT% 個のファイル名を変更します。
) else (
echo %COUNT% 個のファイル名を変更しました。
)
exit /b
rem ------------------------------------------------------------------------
rem ファイル名/フォルダ名を変更する
rem ------------------------------------------------------------------------
:CONVERT
set OLDNAME=%~nx1
set NEWNAME=%OLDNAME%
for %%C in ( a b c d e f g h i j k l m n o p q r s t u v w x y z ) do (
set "NEWNAME=!NEWNAME:%%C=%%C!"
)
if "%OLDNAME%"=="%NEWNAME%" exit /b
if "%QOPT%"=="0" echo %~1 %NEWNAME%
if "%VOPT%"=="0" ren "%~1" "%NEWNAME%"
set /a COUNT=COUNT+1
exit /b
rem ------------------------------------------------------------------------
rem ヘルプメッセージ
rem ------------------------------------------------------------------------
:USAGE
echo ファイル名(複数可)を小文字に変更します。
echo.
echo LCASE2(.CMD) [/R] [/D] [/Q] [/V] [ドライブ:][パス][ファイル名]
echo.
echo /R ファイル/フォルダを再帰的に検索します。
echo /D フォルダ名を変更します。
echo /Q 変更したファイル名を表示しません。
echo /V 変更対象となるファイル名を表示するだけで、変更は行いません。
exit /b
同様にして半角カタカナを全角カタカナに変換する ZCASE2.CMD
および全角英数字・全角スペースを半角文字に変換する HCASE2.CMD
もサブルーチン CONVERT
を差し替えるだけで簡単に作ることができる。ただし,再帰検索を行うオプション /R
とフォルダ名を変更するオプション /D
は同時に指定できないようにした。これは再帰検索中にフォルダ名が変えられてしまうと不都合を生じるからだ。逆に Windows のファイルシステムは大文字・小文字を区別しないため,大文字・小文字を変換するときはオプション /R
とオプション /D
が両立する。
ZCASE2.CMD のソースコードはコチラ
@echo off
rem ------------------------------------------------------------------------
rem ファイル名(複数可)の半角カタカナを全角カタカナに変換する
rem ------------------------------------------------------------------------
setlocal enabledelayedexpansion
set ROPT=0
set DOPT=0
set QOPT=0
set VOPT=0
set COUNT=0
rem ------------------------------------------------------------------------
rem オプション解析
rem ------------------------------------------------------------------------
set ARGS=
if "%~1"=="" goto USAGE
:LOOP
set OPT=%~1
if /I "%OPT%"=="/R" set ROPT=1&&goto ENDIF
if /I "%OPT%"=="/D" set DOPT=1&&goto ENDIF
if /I "%OPT%"=="/Q" set QOPT=1&&goto ENDIF
if /I "%OPT%"=="/V" set VOPT=1&&goto ENDIF
if "%OPT:~0,1%"=="/" goto ERROR
if defined ARGS (
set ARGS=%ARGS% "%~1"
) else (
set ARGS="%~1"
)
:ENDIF
shift
if "%~1"=="" goto BREAK
goto LOOP
:ERRR
echo オプション %OPT% には対応していません!
exit /b
:BREAK
if not defined ARGS (
echo ファイル名を指定して下さい!
exit /b
)
if "%ROPT%%DOPT%"=="11" (
オプション /R とオプション /D は同時に指定できません!
exit /b
)
rem ------------------------------------------------------------------------
rem ファイル名/フォルダ名を変更する
rem ------------------------------------------------------------------------
set DIROPT=/b
if "%DOPT%"=="1" (
set DIROPT=%DIROPT% /ad
) else (
set DIROPT=%DIROPT% /a-d
)
if "%ROPT%"=="1" (
set DIROPT=/s %DIROPT%
)
for /F "usebackq tokens=*" %%I in ( `dir %DIROPT% %ARGS% 2^>NUL` ) do (
call :CONVERT "%%~I"
)
if "%VOPT%"=="1" (
echo %COUNT% 個のファイル名を変更します。
) else (
echo %COUNT% 個のファイル名を変更しました。
)
exit /b
rem ------------------------------------------------------------------------
rem ファイル名/フォルダ名を変更する
rem ------------------------------------------------------------------------
:CONVERT
set OLDNAME=%~nx1
set NEWNAME=%OLDNAME%
set NEWNAME=%NEWNAME:ガ=ガ%
set NEWNAME=%NEWNAME:ギ=ギ%
set NEWNAME=%NEWNAME:グ=グ%
set NEWNAME=%NEWNAME:ゲ=ゲ%
set NEWNAME=%NEWNAME:ゴ=ゴ%
set NEWNAME=%NEWNAME:ザ=ザ%
set NEWNAME=%NEWNAME:ジ=ジ%
set NEWNAME=%NEWNAME:ズ=ズ%
set NEWNAME=%NEWNAME:ゼ=ゼ%
set NEWNAME=%NEWNAME:ゾ=ゾ%
set NEWNAME=%NEWNAME:ダ=ダ%
set NEWNAME=%NEWNAME:ヂ=ヂ%
set NEWNAME=%NEWNAME:ヅ=ヅ%
set NEWNAME=%NEWNAME:デ=デ%
set NEWNAME=%NEWNAME:ド=ド%
set NEWNAME=%NEWNAME:バ=バ%
set NEWNAME=%NEWNAME:ビ=ビ%
set NEWNAME=%NEWNAME:ブ=ブ%
set NEWNAME=%NEWNAME:ベ=ベ%
set NEWNAME=%NEWNAME:ボ=ボ%
set NEWNAME=%NEWNAME:パ=パ%
set NEWNAME=%NEWNAME:ピ=ピ%
set NEWNAME=%NEWNAME:プ=プ%
set NEWNAME=%NEWNAME:ペ=ペ%
set NEWNAME=%NEWNAME:ポ=ポ%
set NEWNAME=%NEWNAME:。=。%
set NEWNAME=%NEWNAME:「=「%
set NEWNAME=%NEWNAME:」=」%
set NEWNAME=%NEWNAME:、=、%
set NEWNAME=%NEWNAME:・=・%
set NEWNAME=%NEWNAME:ヲ=ヲ%
set NEWNAME=%NEWNAME:ァ=ァ%
set NEWNAME=%NEWNAME:ィ=ィ%
set NEWNAME=%NEWNAME:ゥ=ゥ%
set NEWNAME=%NEWNAME:ェ=ェ%
set NEWNAME=%NEWNAME:ォ=ォ%
set NEWNAME=%NEWNAME:ャ=ャ%
set NEWNAME=%NEWNAME:ュ=ュ%
set NEWNAME=%NEWNAME:ョ=ョ%
set NEWNAME=%NEWNAME:ッ=ッ%
set NEWNAME=%NEWNAME:ー=ー%
set NEWNAME=%NEWNAME:ア=ア%
set NEWNAME=%NEWNAME:イ=イ%
set NEWNAME=%NEWNAME:ウ=ウ%
set NEWNAME=%NEWNAME:エ=エ%
set NEWNAME=%NEWNAME:オ=オ%
set NEWNAME=%NEWNAME:カ=カ%
set NEWNAME=%NEWNAME:キ=キ%
set NEWNAME=%NEWNAME:ク=ク%
set NEWNAME=%NEWNAME:ケ=ケ%
set NEWNAME=%NEWNAME:コ=コ%
set NEWNAME=%NEWNAME:サ=サ%
set NEWNAME=%NEWNAME:シ=シ%
set NEWNAME=%NEWNAME:ス=ス%
set NEWNAME=%NEWNAME:セ=セ%
set NEWNAME=%NEWNAME:ソ=ソ%
set NEWNAME=%NEWNAME:タ=タ%
set NEWNAME=%NEWNAME:チ=チ%
set NEWNAME=%NEWNAME:ツ=ツ%
set NEWNAME=%NEWNAME:テ=テ%
set NEWNAME=%NEWNAME:ト=ト%
set NEWNAME=%NEWNAME:ナ=ナ%
set NEWNAME=%NEWNAME:ニ=ニ%
set NEWNAME=%NEWNAME:ヌ=ヌ%
set NEWNAME=%NEWNAME:ネ=ネ%
set NEWNAME=%NEWNAME:ノ=ノ%
set NEWNAME=%NEWNAME:ハ=ハ%
set NEWNAME=%NEWNAME:ヒ=ヒ%
set NEWNAME=%NEWNAME:フ=フ%
set NEWNAME=%NEWNAME:ヘ=ヘ%
set NEWNAME=%NEWNAME:ホ=ホ%
set NEWNAME=%NEWNAME:マ=マ%
set NEWNAME=%NEWNAME:ミ=ミ%
set NEWNAME=%NEWNAME:ム=ム%
set NEWNAME=%NEWNAME:メ=メ%
set NEWNAME=%NEWNAME:モ=モ%
set NEWNAME=%NEWNAME:ヤ=ヤ%
set NEWNAME=%NEWNAME:ユ=ユ%
set NEWNAME=%NEWNAME:ヨ=ヨ%
set NEWNAME=%NEWNAME:ラ=ラ%
set NEWNAME=%NEWNAME:リ=リ%
set NEWNAME=%NEWNAME:ル=ル%
set NEWNAME=%NEWNAME:レ=レ%
set NEWNAME=%NEWNAME:ロ=ロ%
set NEWNAME=%NEWNAME:ワ=ワ%
set NEWNAME=%NEWNAME:ン=ン%
if "%OLDNAME%"=="%NEWNAME%" exit /b
if "%QOPT%"=="0" echo %~1 %NEWNAME%
if "%VOPT%"=="0" ren "%~1" "%NEWNAME%"
exit /b
rem ------------------------------------------------------------------------
rem ヘルプメッセージ
rem ------------------------------------------------------------------------
:USAGE
echo ファイル名(複数可)の半角カタカナを全角カタカナに変換します。
echo.
echo ZCASE2(.CMD) [/R] [/D] [/Q] [/V] [ドライブ:][パス][ファイル名]
echo.
echo /R ファイル/フォルダを再帰的に検索します。
echo /D フォルダ名を変更します。
echo /Q 変更したファイル名を表示しません。
echo /V 変更対象となるファイル名を表示するだけで、変更は行いません。
exit /b
HCASE2.CMD のソースコードはコチラ
@echo off
rem ------------------------------------------------------------------------
rem ファイル名(複数可)の全角英数字・全角スペースを半角文字に変換する
rem ------------------------------------------------------------------------
setlocal enabledelayedexpansion
set ROPT=0
set DOPT=0
set QOPT=0
set VOPT=0
set COUNT=0
rem ------------------------------------------------------------------------
rem オプション解析
rem ------------------------------------------------------------------------
set ARGS=
if "%~1"=="" goto USAGE
:LOOP
set OPT=%~1
if /I "%OPT%"=="/R" set ROPT=1&&goto ENDIF
if /I "%OPT%"=="/D" set DOPT=1&&goto ENDIF
if /I "%OPT%"=="/Q" set QOPT=1&&goto ENDIF
if /I "%OPT%"=="/V" set VOPT=1&&goto ENDIF
if "%OPT:~0,1%"=="/" goto ERROR
if defined ARGS (
set ARGS=%ARGS% "%~1"
) else (
set ARGS="%~1"
)
:ENDIF
shift
if "%~1"=="" goto BREAK
goto LOOP
:ERROR
echo オプション %OPT% には対応していません!
exit /b
:BREAK
if not defined ARGS (
echo ファイル名を指定して下さい!
exit /b
)
if "%ROPT%%DOPT%"=="11" (
オプション /R とオプション /D は同時に指定できません!
exit /b
)
rem ------------------------------------------------------------------------
rem ファイル名/フォルダ名を変更する
rem ------------------------------------------------------------------------
set DIROPT=/b
if "%DOPT%"=="1" (
set DIROPT=%DIROPT% /ad
) else (
set DIROPT=%DIROPT% /a-d
)
if "%ROPT%"=="1" (
set DIROPT=/s %DIROPT%
)
for /F "usebackq tokens=*" %%I in ( `dir %DIROPT% %ARGS% 2^>NUL` ) do (
call :CONVERT "%%~I"
)
if "%VOPT%"=="1" (
echo %COUNT% 個のファイル名を変更します。
) else (
echo %COUNT% 個のファイル名を変更しました。
)
exit /b
rem ------------------------------------------------------------------------
rem ファイル名/フォルダ名を変更する
rem ------------------------------------------------------------------------
:CONVERT
set OLDNAME=%~nx1
set NEWNAME=%OLDNAME%
set NEWNAME=%NEWNAME: = %
set NEWNAME=%NEWNAME:0=0%
set NEWNAME=%NEWNAME:1=1%
set NEWNAME=%NEWNAME:2=2%
set NEWNAME=%NEWNAME:3=3%
set NEWNAME=%NEWNAME:4=4%
set NEWNAME=%NEWNAME:5=5%
set NEWNAME=%NEWNAME:6=6%
set NEWNAME=%NEWNAME:7=7%
set NEWNAME=%NEWNAME:8=8%
set NEWNAME=%NEWNAME:9=9%
set NEWNAME=%NEWNAME:A=A%
set NEWNAME=%NEWNAME:B=B%
set NEWNAME=%NEWNAME:C=C%
set NEWNAME=%NEWNAME:D=D%
set NEWNAME=%NEWNAME:E=E%
set NEWNAME=%NEWNAME:F=F%
set NEWNAME=%NEWNAME:G=G%
set NEWNAME=%NEWNAME:H=H%
set NEWNAME=%NEWNAME:I=I%
set NEWNAME=%NEWNAME:J=J%
set NEWNAME=%NEWNAME:K=K%
set NEWNAME=%NEWNAME:L=L%
set NEWNAME=%NEWNAME:M=M%
set NEWNAME=%NEWNAME:N=N%
set NEWNAME=%NEWNAME:O=O%
set NEWNAME=%NEWNAME:P=P%
set NEWNAME=%NEWNAME:Q=Q%
set NEWNAME=%NEWNAME:R=R%
set NEWNAME=%NEWNAME:S=S%
set NEWNAME=%NEWNAME:T=T%
set NEWNAME=%NEWNAME:U=U%
set NEWNAME=%NEWNAME:V=V%
set NEWNAME=%NEWNAME:W=W%
set NEWNAME=%NEWNAME:X=X%
set NEWNAME=%NEWNAME:Y=Y%
set NEWNAME=%NEWNAME:Z=Z%
set NEWNAME=%NEWNAME:a=a%
set NEWNAME=%NEWNAME:b=b%
set NEWNAME=%NEWNAME:c=c%
set NEWNAME=%NEWNAME:d=d%
set NEWNAME=%NEWNAME:e=e%
set NEWNAME=%NEWNAME:f=f%
set NEWNAME=%NEWNAME:g=g%
set NEWNAME=%NEWNAME:h=h%
set NEWNAME=%NEWNAME:i=i%
set NEWNAME=%NEWNAME:j=j%
set NEWNAME=%NEWNAME:k=k%
set NEWNAME=%NEWNAME:l=l%
set NEWNAME=%NEWNAME:m=m%
set NEWNAME=%NEWNAME:n=n%
set NEWNAME=%NEWNAME:o=o%
set NEWNAME=%NEWNAME:p=p%
set NEWNAME=%NEWNAME:q=q%
set NEWNAME=%NEWNAME:r=r%
set NEWNAME=%NEWNAME:s=s%
set NEWNAME=%NEWNAME:t=t%
set NEWNAME=%NEWNAME:u=u%
set NEWNAME=%NEWNAME:v=v%
set NEWNAME=%NEWNAME:w=w%
set NEWNAME=%NEWNAME:x=x%
set NEWNAME=%NEWNAME:y=y%
set NEWNAME=%NEWNAME:z=z%
if "%OLDNAME%"=="%NEWNAME%" exit /b
if "%QOPT%"=="0" echo %~1 %NEWNAME%
if "%VOPT%"=="0" ren "%~1" "%NEWNAME%"
exit /b
rem ------------------------------------------------------------------------
rem ヘルプメッセージ
rem ------------------------------------------------------------------------
:USAGE
echo ファイル名(複数可)の全角英数字・全角スペースを半角文字に変換する
echo.
echo HCASE2(.CMD) [/R] [/D] [/Q] [/V] [ドライブ:][パス][ファイル名]
echo.
echo /R ファイル/フォルダを再帰的に検索します。
echo /D フォルダ名を変更します。
echo /Q 変更したファイル名を表示しません。
echo /V 変更対象となるファイル名を表示するだけで、変更は行いません。
exit /b
参考文献
残念ながらバッチファイルでアスタリスク文字 *
を一括置換する方法は存在しない様子。
下記文献を見る限り ForFiles
コマンドは高機能なのだが,いろいろ癖(フォルダパスに日本語が含まれているとエラーになる等)があって大変そうだ。せめて実行スピードが速かったら頑張って使いこなそうとやる気が出るのだが。