【BAT】複数フォルダ内を拡張子で抽出してコピーや削除する方法

  • 0
    いいね
  • 0
    コメント

    はじめに

    あるフォルダを世代別バックアップしているため、フォルダ名に日時(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コマンドがあります。
    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スクリプトを組まなくともバッチでフォルダ内を再帰できるようになったので、今後活用していきたい。