ModSrlCmd
環境
Microsoft Windows [Version 10.0.14393]
概要?
ファイル移動に伴って連番がバラバラになってしまうことがある。
手で修正するのはちょっと。。。
できること。
指定したディレクトリ配下にあるファイルに、連番をつけ直す
(aaa34.txt,aaa32.txt → aaa01.txt,aaa02.txt)
出力先は、指定したディレクトリ直下に作成したModSrlCmd.tmpディレクトリの直下。
((sourceDirPath)\(sourcefiles) -> (sourceDirPath)\(sourcefiles)…\(ModSrlCmd.tmp)\(newfiles)
条件
対象ファイルの連番の桁は揃ってなければならない。
(aaa01.txt, aaa003.txtは許していない。)
連番を元より大きい数字で始める場合、桁上がりが問題となる。
(aaa00.txt,…aaa99.txt → aaa01.txt,…aaa100.txtとはならない。
引数
一つ目: ファイル群が存在するディレクトリのパス
必須
二つ目: 現在の連番の桁数(aa00.txt,aa01.txtなら2)
必須
三つ目: 新しい初項の値。ただし上位の0は抜く(aaa01.txt,aaa02.txtとしたいなら1)
四つ目が必要ないなら任意。規定値は1。
四つ目: 桁数を上げたい場合、上がる桁数(aaa01.txtをaaa0001.txtにするなら2)
任意。規定値は0。
bat コード
@rem --------------------------------
@rem 結果出力をなしに
@echo off
rem 遅延環境変数
setlocal EnableDelayedExpansion
rem ---------------------------------
rem - 連番をつけ直すスクリプト -
rem ---------------------------------
rem ---------------------------------
rem エラー判定フラグを生成
set /a flg=0
rem ---------------------------------
rem 引数に対する処理
rem 引数(ディレクトリ)を受け取って、フルパスに変更
set path=%~f1
if not exist %path% (
echo there is not the path.
echo exit.
exit /b 1
)
rem 引数(ディレクトリ配下のフォルダの連番の桁数)を指定
rem 初期値?は0(連番が存在しない)
if not {%2}=={} if not {%2}=={0} (
set /a srlnum=%2
) else (
echo ^%2 is empty or 0.
echo exit.
exit /b 1
)
rem %3は初項の値
rem 初項の初期値は1
if {%3}=={} (set /a cnt=1) else (set /a cnt=%3)
rem 連番の桁数を%4個上げる。
rem 当然初期値は0。
if {%4}=={} (set /a exp=1) else (
set /a exp=1
for /l %%i in (1,1,%4) do (set /a exp*=10)
)
rem renを使って名前を変更するのではなく
rem 新しいファイルにコピーする
set exportDir=%path%\ModSrlCmd.tmp
if not exist %exportDir% (
mkdir %exportDir%
) else (
echo ModSrlCmd.tmp directory is.
echo so this cmd is error.
exit /b
)
rem ---------------------------------
rem 引数配下にあるファイルに対してren
for /f %%i in ( 'dir /b %path%' ) do (
rem コピー先ディレクトリ自身の時は終える
if %%i==ModSrlCmd.tmp ( goto :EOF )
setlocal
rem 連番を修正するファイルの拡張子を外す
call :getChildItem %%i
call :getExt %%i
rem ChildItem(連番を修正するファイル)の長さを得る。
call :getLength !ChildItem!
set ciLg=!Length!
set /a nameLg=!ciLg!-!srlnum!
rem Nameに連番抜きファイル名を代入
rem どうしてこうするときちんと動くのかはよくわかっていない。
call :getName !ChildItem! !nameLg!
set ciNm=!Name!
rem 連番上桁の0を作成
call :getZeros !srlnum! !cnt! !exp!
set srlZeros=!Zeros!
rem 連番を除いたファイル名・連番上桁の0・連番下桁の数・拡張子をそれぞれ繋げる
set itemName=!ciNm!!srlZeros!!cnt!!Ext!
copy %path%\!ChildItem!!Ext! %exportDir%\!itemName!
endlocal
set /a cnt+=1
)
:EOF
exit /b 0
:getChildItem
set ChildItem=
set ChildItem=%~n1
exit /b
:getExt
set Ext=
set Ext=%~x1
exit /b
:getLength
set Length=
set getLength_Item=%1
set /a length=0
:getLength_loop
if {!getLength_Item!}=={} (
exit /b
) else (
set /a length+=1
set getLength_Item=%getLength_Item:~1%
)
goto getLength_loop
exit /b
:getName
set Name=
set getname_tmp=%1
set Name=!getname_tmp:~0,%2!
exit /b
:getZeros
set Zeros=
rem srlnum:現在の連番の桁数(1,2,3,///)
rem srlexp:連番の位(1,10,100,///)
rem exp:現在から上げたい位((10->10)->1, (10->100)->10, ///)
rem tgtnum:欲しい0の数の位(-->0, 0->1, 00->10, ///)
rem cnt:(初め)現在の連番の数 -> 現在の連番の数*(10の倍数)
set /a getZeros_srlexp=1
set /a getZeros_srlnum=%1-1
for /l %%i in (1,1,!getZeros_srlnum!) do ( set /a getZeros_srlexp*=10)
if {%2}=={0} ( set /a getZeros_cnt=1 ) else (set /a getZeros_cnt=%2)
set /a getZeros_exp=%3
set /a getZeros_tgtnum=!getZeros_srlexp!*!getZeros_exp!
:getZeros_loop
if !getZeros_cnt! geq !getZeros_tgtnum! (
exit /b
) else (
if {!Zeros!}=={} (
set Zeros=0
) else (
set Zeros=0!Zeros!
)
set /a getZeros_cnt*=10
)
goto :getZeros_loop
exit /b
endlocal
反省
batファイルの文字コードは初めからsjisにしましょう。
エラーが鬱陶しい。
課題
できたらいいな
コードが冗長な気がする。もっと短く書きたい。
powershellでも同じものを作りたい。(勉強)
書き方の統一(途中でこっちのがよい、という方に書き方が変わった。コーディング規約が統一されていないのは、後々の整備が大変。)
元々あるファイル群を新規作成したディレクトリ下に置いて、新しくコピーしたファイル群を指定ディレクトリ直下に置く方がよかったか?
できない?
引数を受け取るとき、(バッチファイル名) /a (引数) で引数を指定することはできないのか?
どこにもできるとは書いてないが、出来ないとも書いてない気が。
後書き
powershellにはバージョンがあってやーねー。
参考URL
引数の取り方
【Windows】バッチファイルの引数 at softelメモ
dirコマンドでファイル名のみ出力する方法
Tech TIPS:Windowsのdirコマンドでファイル名の一覧を取得する - @IT
gotoコマンドの書き方
Goto - DOS コマンド一覧 - Programming Field
文字列の切り出しかた
BATファイルで文字列の切り出し
.bat(バッチファイル)のifコマンド解説。 - Qiita