min117の日記

初期desireもち。趣味Mac,メインFedora,仕事xp。

Windows ファイル名の半角空白文字をアンダーバーに置き換えるバッチ

Windowsファイル名に半角空白が入ったファイル名は本当に扱いにくい。

例えば

for /F %i in ('dir /b') do @echo %i

なんてやったときに、ファイル名に半角空白があるとデリミタと解釈されちゃってtokenが複数入ってしまうなんてことになる。

 

これを防ぐために半角空白を全てアンダーバーに変えてしまうバッチを作る。動きはこんな感じ。

「コンピューター - ショートカット.lnk」というファイルがあったとして…

f:id:min117:20180220233048p:plain

今回作ったバッチ「blank空白を消すバッチ.bat」をコマンドプロンプトから引数なしで起動実行すると

f:id:min117:20180220233058p:plain

ファイル名を変更する前後でどうなるかを表示してくれる。引数なしなので(変更後どうなるかを表示するだけで)実際にファイル名の変更は行わない

f:id:min117:20180220233154p:plain

同じバッチファイルを引数Yをつけて実行すると

cmd> blank空白を消すバッチ.bat Y

f:id:min117:20180220233213p:plain

今度はファイル名の変更を実行する。半角空白がアンダーバーになっているのがわかる。

f:id:min117:20180220233328p:plain

ソースはこれ。

f:id:min117:20180220234118p:plain

f:id:min117:20180220234129p:plain

<注意点>

① 遅延変数

 @setlocal enabledelayedexpansion @endlocal

② for文のデリミタ空白以外にする(今回はスラッシュにした)

 for /F "delims=/" %%i in ('dir /b ^| find " "') do (

for文の内部で文字列の置き換えいったん変数に入れる(set)必要あり

 set "var=%var:変更前=変更後%"

④ if文で引数1の有無を調べるときはダミー文字列xxをつける

 if xx%1==xx (

⑤ REMで始まる行はコメント

 自分用のメモだけど、よく使うものばかりなので残してある。

 

<ソース>
@echo off
@setlocal enabledelayedexpansion

@cls

ECHO. *------------------------------------------------*
ECHO. * 空白削除バッチ *
ECHO. *------------------------------------------------*
ECHO. バッチファイル名:%~n0%~x0
ECHO. %~n0 本体部分名:%~n0
ECHO. %~x0  拡張子名:%~x0
ECHO.
ECHO. 今いるフォルダで「d:\blank空白を消すバッチ.bat」すれば
ECHO. そのフォルダの中について空白削除される
ECHO ~~~~~~~~~~~~~~~~~~~~~~~~
ECHO. ===========================
ECHO. 引数にYを指定したらmove実行
ECHO. ===========================
ECHO.

ECHO %1 変更実行:%1
ECHO ~~~~~~~~~~~~
ECHO 中止する場合は「Ctrl+C」を実行してください
ECHO.
PAUSE

REM ##### 変数定義 #####
SET WK_DATE=%date:~0,4%%date:~5,2%%date:~8,2%
SET WK_TIME=%time:~0,2%%time:~3,2%%time:~6,2%%time:~9,2%
SET WK_DIR=D$\
SET BATCHPATH=%~DP0
REM ~~~~~~~~~~D:\
REM CD /D %BATCHPATH%
SET LOGNM=%BATCHPATH%%WK_DATE%_ログ.txt

REM echo %time% & echo %time:~0,2%%time:~3,2%%time:~6,2%%time:~9,2%
REM 11:32:48.33
REM 11324833

REM ##### 前ログ削除 #####
REM if exist %LOGNM% (
REM echo Y | del %LOGNM%
REM )

REM ##### 処理実行 #####
for /F "delims=/" %%i in ('dir /b ^| find " "') do (
set src=%%i
@echo 変更前:!src!

REM set "line=%line:3=4%" <---- set "var=%var:変更前=変更後%"

REM @echo !src: =_!
set "dst=!src: =_!"
@echo 変更後:!dst!

REM 引数が空かどうかチェック。なければエラーにする。先頭に「xx」を付けて、空にならないようにしている
REM http://www.atmarkit.co.jp/ait/articles/1506/26/news026_2.html
REM これらは特に、片方が空文字列の場合に注意が必要である。例えば引数が1つ以上あるかどうか判定するために「if %1=="" echo error」としても、%1が空文字列だと「if =="" echo error」と解釈され、これは構文エラーとなる。文字列を比較したい場合は、空文字列でも問題ないように、両方に何かのダミー文字列を付けたり、引用符で囲んだりすること。例えば「if "%1"=="" echo error」や「if /%1==/ echo error」のようにする(バッチファイルでは、文字列を引用符で囲む必然性はない)。

if xx%1==xx (
@echo 変更しません
) else (
@move "!src!" !dst!
)

@echo ==========
)

@endlocal


PAUSE

 

<改良点1>

あとはこれ、このままCドライブ直下で実行してしまうと悲惨な事故になりそう(例えば Program_Files なんてことになりかねない)なので、Cドライブ直下で実行したらエラーで抜ける処理を実装することにする。週末に試す。

<改良点2>

ファイル名に感嘆符(ビックリマーク!)やエスケープ文字(円マーク¥)が含まれているときの動作もテスト必要。