はじめに
あるフォルダを世代別バックアップしているため、フォルダ名に日時(yyyyMMddHHmmss)が付いた状態になっているが、配下のフォルダ構成は同じという状態で実績データ(CSVファイル)を取得したいという依頼があった。
親フォルダの名前が違うというのが面倒なところで、ファイルエクスプローラーの検索のように「*.csv」とすれば、親フォルダに関係なくCSVファイルが抽出できればいいのだが、バッチによるやり方がピンと来なかった。
以前、別件で同様のフォルダ構成でEXEのバージョンを取得してログ出力するVBSスクリプトを組んだこともあって、それを改変して作成した。
目的のものを作り終えたが、バッチでもやり方があるのではないかと検索して、下記サイトに辿り着いた。
指定した名前のディレクトリを再帰的に削除するコマンドライン - IIJIMASの日記
対応
FOR /Rコマンド
このサイトの記事によれば、「FOR /R」とすることでサブフォルダーも処理対象に出来るとのこと。
FOR /R [[ドライブ:]パス] %変数 IN (セット) DO コマンド [コマンド パラメーター]
[ドライブ:]パスから始めて、ツリーの各ディレクトリで FOR 文を実行し
ます。/R の後にディレクトリが指定されていない場合は、現在の
ディレクトリが使用されます。セットが単一のピリオド (.) である場合は、
ディレクトリ ツリーの列挙だけを行います。
以下のようにすれば再帰的にフォルダを検索して処理コマンドを実行できるようです。
"%%f"には、対象のファイル名がセットされる。
for /R %%f in (フォルダ名) do 処理コマンド "%%f"
forfilesコマンド【追記 2017/06/06】
Windows 7やWindows Server 2008以降なら、forfilesコマンドがあります。
/Sオプションを付けることで、サブフォルダーも処理対象に出来ます。
forコマンドでは特定の更新日付を持つファイルだけを抽出することはできないですが、forfilesコマンドなら一定期間経過したファイルを削除することができます。
Windowsのforfilesコマンドで条件に合うファイルを取り出して処理する
forfiles [/P パス名(検索を開始するパス)] [/M 検索マスク] [/S] [/C コマンド] [/D [+ | -] {yyyy/MM/dd | dd}]
変数 | 意味 |
---|---|
@file | ファイル名(拡張子も含む) |
@fname | 拡張子無しの基本ファイル名部分 |
@ext | 拡張子 |
@path | ファイルのフルパス名 |
@relpath | 開始フォルダーからのファイルの相対パス名 |
@isdir | フォルダー名ならTRUE、ファイル名ならFALSE。if内部コマンドと組み合わせ、「/C "cmd /c if @isdir==FALSE notepad.exe @file"」などのように利用する |
@fsize | ファイルサイズ(bytes単位) |
@fdate | ファイルの更新日 |
@ftime | ファイルの更新時間 |
ファイルコピー
CSVファイルをtargetフォルダにコピーする。
同一ファイルがあった場合、XCOPYのDオプションにより送り側の日付が受け側の日付より 新しいファイルだけをコピーします。
for /R %%f in (*.csv) do xcopy /D /I /Y "%%f" target
ファイル削除
gitを使用していた作業フォルダを移す場合、邪魔なgitkeepとgitignoreファイルを一掃します。
for /R %%f in (*.gitkeep, *.gitignore) do del /S /Q "%%f"
一定期間以降を削除
IISログを2ヶ月分残して削除する。2ヶ月は61日として指定。
forfiles /P "C:\inetpub\logs\LogFiles\W3SVC1" /M *.log /C "cmd /c if @isdir==FALSE del /s @path" /D -61 >> iislogdel.log
フォルダ削除
gitを使用していた作業フォルダを移す場合、邪魔なgitフォルダとVisual Studioのvsフォルダを一掃します。
for /R %%f in (.git,.vs) do rmdir /S /Q "%%f"
最後に
バッチ処理でfor文コマンドはたまに使用していたが、「R」コマンドについては知らなかった。これでVBSスクリプトを組まなくともバッチでフォルダ内を再帰できるようになったので、今後活用していきたい。