LoginSignup
0
1

More than 5 years have passed since last update.

batで連番を付け直す

Last updated at Posted at 2016-09-22

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

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1