日付の古いファイルを 一括でoldフォルダへ仕分けるバッチ


概要

ファイルを更新する時に、更新前のファイルももしもの時のために残したい。
そんな時に使うのがGit、Subversion、シャドウコピーのいずれかを利用されているかも知れませんが、
ユーザーが手動で明示的に前のバージョンのファイルを残しているというプロジェクトもあると思います。

例えば、

  1. ファイルの末尾に(拡張子の手前)、日付を表す数字を付ける。
    例) scoresheet_20190602-1456.xlsx
  2. ファイルの末尾に(拡張子の手前)、バージョン番号を表す数字を付ける。
    例) scoresheetv3.xlsx
  3. ファイル一式をアーカイブファイルに収めて圧縮を施す。
    例) result_20190604.tar.gz

上記の方法でファイルのバージョンを管理している場合に
同じディレクトリ内に更新したファイルを次々に作ってしまうと
ディレクトリの中が煩雑になってしまい、ファイルを探すのに余計な時間が掛かってしまいます。

今回はそんな状況に役立つ、古いファイルを仕分けるバッチファイルを作りました。

環境

Windows 10, 7

使用方法

  • 古いファイルを仕分けたいフォルダを選択し、バッチファイルにDrag&Dropします(ファイルパスが引数に指定されてバッチが起動します)。

  • ファイルへのD&Dが困難な場合は、バッチファイルを単体で起動するとフォルダパスの入力を求められるため、ファイルをD&Dして [Enter]キーを押下します。ファイルパス(改行区切りで複数可能)をペーストする方法もあります。

注意

  • 既定では、上記 1., 3. のように "_" でバージョン部分が区切られたファイル群に対応しています。"v4"などで管理しているファイル群を仕分けたい場合は、バッチファイル中の "tSearch" の値を変更してご使用下さい。
  • リネームされるのは、指定したディレクトリ直下のファイルのみとなります。現在のコーディング設計上、古いファイルを直下のoldフォルダに移動させる仕様のため、サブディレクトリ以下も対象とするには不向きです。
  • コマンドプロンプトの仕様上、"\filesvr\folder1\" のようなネットワークパスを扱えないため、予めドライブ割当をしておく必要があります。
  • バッチファイルの構文解析の仕様上、ファイル名中の記号によっては正しく処理できない可能性があります。
  • ファイルに対しての変更は移動コマンドを使用しています。基本的にデータが消失する事はありません。
  • 但し、ファイル管理が特殊な環境の場合はご注意願います。万が一ファイルを紛失されても、筆者では補償は一切致しかねます。

※「えぇー! めっちゃ遅いでー。待つのは いやや」って言いたくなるくらいに、このバッチファイルは動作が遅いです。文字列を末尾から1文字ずつ切り取っていく処理に時間が掛かるんです。他の言語ならもっと短いステップで実現できるでしょうけど、急ぎでもないと思いますので、このバッチを実行したまま放置しておいて下さい。
改修しました。

ソースファイル

「かんたん生成」するには、B642File.batを起動して本ページ全体のテキストをコピペして下さい。
その後、生成したZIPファイルを解凍して任意の場所へ配置して下さい。

興味ある方は、以下のコードをご覧ください。

コード

MoveOld.bat
@ECHO OFF
COLOR 0A

ECHO ############# MoveOld.bat ##############
ECHO # Move old files by using date         #
ECHO #                in the filename batch #
ECHO #                                      #
ECHO #   1st release: 2019-06-03            #
ECHO #   Last update: 2019-10-01            #
ECHO #   Author: Y. Kosaka                  #
ECHO #   See the web for more information   #
ECHO #   https://qiita.com/x-ia             #
ECHO ########################################

SET tScr=%~n0
SET dScr=%~dp0
SET extLog=.log
SET fList=%~dp0%tScr%-list.txt
SET dOld=old
SET nLine=0
SET nLineMove=0
SET nLineMax=0
SET tName1=_

:loop
SET pFolder=
SET pInput=%1
CALL :dInput "%pInput:"=%"
IF "%pFolder:"=%" EQU "" GOTO eof
IF NOT DEFINED pFolder GOTO eof
IF NOT EXIST %pFolder% (
  ECHO File not exists.
  SHIFT
  GOTO loop
)

PUSHD %pFolder%

DIR /A-D-L /B /OE-N %pFolder%>%fList%

FOR /F "delims=" %%A IN (%fList%) DO (
SET /A nLineMax+=1
)

FOR /F "delims=" %%A IN (%fList%) DO (
  CALL :divname "%%A"
  CALL :compare "%%A"
)
ECHO.
POPD
SHIFT
GOTO loop
EXIT /B

:dInput
ECHO.
IF %1 NEQ "" (
  SET pFolder=%1
) ELSE (
  ECHO Current directory = %~dp0
  ECHO.
  ECHO Enter the folder path within files to move old files.
  SET /P pFolder=folder path= 
)

SET pFolder="%pFolder%"
SET pFolder="%pFolder:"=%"
ECHO Input folder:
ECHO %pFolder%

IF %pFolder% EQU "" EXIT /B
ECHO "%pFolder%" | FIND /I "\" >NUL
IF ERRORLEVEL 1 SET pFolder=%~dp0%pFolder%
SET pFolder="%pFolder:"=%"
EXIT /B

:divname
SET tName="%~n1"
SET tExt="%~x1"
SET flag=

CALL :rmver %tName:_=..%
EXIT /B

:rmver
SET tName="%~n1%tExt%"
EXIT /B

:compare
SET /A nLine+=1
IF "%tName:"=%_" EQU "%tName1:"=%_" (
  CALL :movefile %1
)
TITLE %tScr% %nLineMove%/%nLine%/%nLineMax%
SET tName1=%tName%
EXIT /B

:movefile
SET tFile=%1
ECHO %tFile:^^=^% -^> %dOld%
IF NOT EXIST "%pFolder:"=%\%dOld%" (
  MKDIR "%pFolder:"=%\%dOld%"
)
MOVE %tFile:^^=^% .\%dOld%
SET err=%ERRORLEVEL%
IF %err%. EQU 0. (
  SET /A nLineMove+=1
)
ECHO %date% %time%   %tScr% %err%   %tFile:^^=^%>>%dScr%\%tScr%%extLog%
EXIT /B

:eof
ECHO Terminated. 
PAUSE

バイナリ (Base64 encoding)

MoveOld.zip
---
UEsDBBQAAAAIAPG6W08tCCbVBwQAAPIJAAALAAAATW92ZU9sZC5iYXSNVltvm0gU
fo4l/4cjqpFq7QJmV6pUJKwlYbxBJeDaTtVKUSJij2O0NnhhnLpSld++Zy5gsJNV
58FmznxzLt+5wF/06jqBZDzu966SKJnC0O/3pvQGZnQeJVd+BDT2LyMa0Mj/hr9f
J348C5O43+v35NV37QU3xTNLNkvrMeXdk3c1XEKg2CxhlW1YBY8/YF9l+RMsU86g
Xkf4ycpy4Gsm7+bplgEaWqzfhr++2nCn4lCyDUsr5sIfQ+ejOfxgDv98Cx6liN/v
hLMa7gzNofMW3N/zdVG68M2CT0WV/pPC2WrDZ4zJ8L6zR1gVJWyLkmHI+LhNeVbk
J/A157vKte1/s4yn1qLY2gcz65po4L+4RF4x9cBni9IjL/lQbZdqu9zpPTvwqHjy
rE3xpASrKKu4QhBxl5gbFFj8wJtyQp0sLRdr70HrxELxsBDULo+ynHnD1kYUSleQ
Huo9jzH5jtDU77mbotgp8W6M+ljp6V2Y7/bolIO17UcRuEspAIOoE9fwiNHvhWMh
UTelCOjnWzAM+DuZJ8CKlYTEyRwCOg5jGtRmzgH0azibQ62MwPt+D0DyP8aChbzg
yBzyUlniYHYdjufiQepRUQxERJPb2XVwVCNEQTgF2zcDMwL7EuyEmvERMCKSfgkc
Yw/bGNGSbbJt5RlAiA9hDO81ZgBBIvwSBNl+Q+xvnqON/6oCAE1q9iw70UCccRRj
Ne7SshEPVB1i3JNkEqB5FXsrcuQOPboULmBOVaqaS8gvcSCmn0VepPF2ukWGB0Cj
GW0xfrUvS5ZzWGYlW/Ci/AEe6ApWCKuB0pxjNuVcUYndpXwN3zO+xnGjxhQvsBnb
g8uqnbAnjR+t2x5oOtt+NmUmyu7VA12S0itVrEqnq2WdmhCkNKWma7ZhUcJbBuEn
YPEGYIdg3Bkwim8jqYFOp8k0ol9oBE6XVNnLR3v/5+9Z9lRNtHoVr7zkjg6b0wMX
gkMtWG3SJ0/cFKPCrdbZiqv7zegQN4jU5L6YDiFCQFrn0kYNGP6OEHWoaRBw6evP
hgSixxExFBcCXbdxm5MmshagHgTSnqg5cQZtT5yOTHhfCzr6BupPtkEr7Hpgldtn
rCcd1oNnWaTDtDo/Y1mRY5wmRXdkt/Vl38sJqIwgRw96ACqJo0WtjheNIHoAiJoZ
83AeUVBjH0gzu4mtnut/nDKkM72VAXLqZ61eY8XklHyqBpB79/7euydg3o+AiNcI
OZnAnfq8UxAdws0nMUpfBchgbpIvtGvFuqttyDdfia1xLBBlmaCUWJK2oXWcT818
xYjqAauiEN8PyBXPMP4LTd2F1HLRtj0aEfHmRQ8lgqjX7hlj8hUkFc9Zuc1yVL60
cABN/NsZ1X0QB/Jzrt/7D1BLAQIUABQAAAAIAPG6W08tCCbVBwQAAPIJAAALAAAA
AAAAAAEAIAAAAAAAAABNb3ZlT2xkLmJhdFBLBQYAAAAAAQABADkAAAAwBAAAAAA=
---