DOSバッチで「新しいファイルをn個だけ残す」の書き方

環境

  • WindowsXPsp3、Windows2008R2
  • DOS窓

目的

  • バックアップファイルのローテーションなどで、無限にログファイルの個数が増えるのを防止したい時。
  • その為にDOSバッチだけで何とかしたい時

対処

DOSコマンドの「for」を使うのが良いようです。
 

C:\Documents and Settings\hogehoge>help for
指定されたコマンドをファイル セットの各ファイルに対して実行します。

FOR %変数 IN (セット) DO コマンド [コマンドパラメータ]

  %変数     単一文字の置き換え可能なパラメータを指定します。
  (セット)  ファイル セットを指定します。ワイルドカードを使用できます。
  コマンド  各ファイルごとに実行するコマンドを指定します。
  コマンドパラメータ
            指定されたコマンドのパラメータまたはスイッチを指定します。

バッチ プログラムで FOR コマンドを使用するときは、%変数の代わりに、
%%変数を使用してください。変数名では大文字と小文字が区別されるため、
%i と %I は異なります。

コマンド拡張機能を有効にすると、次の FOR コマンドの追加形式
がサポートされるようになります:

FOR /D %変数 IN (セット) DO コマンド [コマンドパラメータ]

    セットがワイルドカードを含む場合は、ファイル名ではなくディレクトリ名
    の一致を指定します。

FOR /R [[ドライブ:]パス] %変数 IN (セット) DO コマンド [コマンドパラメータ]

    [ドライブ:]パスから始めて、ツリーの各ディレクトリで FOR 文を実行し
    ます。/R の後にディレクトリが指定されていない場合は、現在の
    ディレクトリが使用されます。セットが単一のピリオド (.) である場合は、
    ディレクトリ ツリーの列挙だけを行います。


FOR /L %変数 IN (開始,ステップ,終了) DO コマンド [コマンドパラメータ]

    セットは、ステップの量ごとに変化する開始から終了までの数列です。
    たとえば、(1,1,5) は 1 2 3 4 5、(5,-1,1) は (5 4 3 2 1) という数列に
    なります。

FOR /F ["オプション"] %変数 IN (ファイル セット) DO コマンド
       [コマンド パラメータ]
FOR /F ["オプション"] %変数 IN ("文字列") DO コマンド [コマンド パラメータ]
FOR /F ["オプション"] %変数 IN ('コマンド') DO コマンド [コマンド パラメータ]

    または usebackq オプションの場合:

FOR /F ["オプション"] %変数 IN (ファイル セット) DO コマンド
       [コマンド パラメータ]
FOR /F ["オプション"] %変数 IN ('文字列') DO コマンド [コマンド パラメータ]
FOR /F ["オプション"] %変数 IN (`コマンド`) DO コマンド [コマンド パラメータ]

    ファイル名セットは、1 つ以上のファイル名です。各ファイルが開かれ、読み
    取られ、処理されてから、ファイル名セットの次のファイルに進みます。処理
    には、ファイルの読み取り、個々のテキスト行への分割と、0 個以上のトークン
    への解析が含まれます。その後、変数値を見つかったトークン文字列に設定して、
    for ループの本体が呼び出されます。既定では、/F は、各ファイルの各行から、
    空白で区切られた最初のトークンを渡します。空白行はスキップされます。既定
    の解析動作を変更するには、オプションの "オプション" パラメータを指定しま
    す。これは、異なる解析オプションを指定する 1 つ以上のキーワードを含む、
    引用符で囲まれた文字列です。キーワードは、次のとおりです:

        eol=c           - 行末のコメント文字を指定します (1 文字)。
        skip=n          - ファイルの先頭でスキップする行数を指定します。
        delims=xxx      - 区切り文字のセットを指定します。これは、既定の
                          区切り文字であるスペースとタブを置き換えます。
        tokens=x,y,m-n  - 各繰り返しに対して、各行から for 本体に渡すトー
                          クンを指定します。これにより、追加の変数名が割り当
                          てられます。m-n の形式は範囲で、m 番目から n 番目の
                          トークンを指定します。tokens= 文字列の最後の文字が
                          アスタリスクである場合は、追加の変数が割り当てられ、
                          最後のトークンが解析された後、行に含まれている残り
                          のテキストを受け取ります。
        usebackq        - 次の新しい表示形式を指定します。逆引用符で囲まれた
                          文字列がコマンドとして実行され、一重引用符で囲まれた
                          文字列がリテラル文字列コマンドになりファイル名セット
                          のファイル名を二重引用符で囲めるようになります。

    例を参考にしてください:

FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k


    この例は、myfile.txt の各行を解析します。セミコロンで始まる行を無視し、
    各行の 2 番目と 3 番目のトークンを for 本体に渡します。トークンは、カンマ
    またはスペースで区切られています。for 本体の文が %i で 2 番目のトークン
    を、%j で 3 番目のトークンを取得し、%k で 3 番目以降のすべてのトークンを
    取得していることに注意してください。スペースを含むファイル名に対しては、
    二重引用符でファイル名を引用する必要があります。この方法で二重引用符を使う
    ためには、usebackq オプションを使わなければなりません。使わなければ、二重
    引用符はリテラル文字列の定義として解釈され、解析されます。

    %i は for 文で明示的に宣言され、%j と %k は tokens= オプションで暗黙的に
    宣言されています。tokens= 行を使って 26 個までのトークンを指定できますが、
    文字 'z' または 'Z' よりも高い変数を宣言することはできません。FOR 変数名は
    単一の文字で、大文字と小文字を区別し、グローバルなものであり、一度にアクティ
    ブにできるのは合計 52 個までです。

    また、カッコで囲んだファイル名セットを一重引用符で囲み、文字列にすることに
    より、即時の文字列に対する FOR /F 解析ロジックを使うこともできます。
    これは、ファイルからの単一入力行として処理されます。

    最後に、FOR /F コマンドを使って、コマンド出力を解析することができます。
    カッコの中のファイル名セットを逆引用符で囲みます。この文字列は、コマンド
    ラインとして子 CMD.EXE に渡されます。出力はメモリにキャプチャされ、ファイ
    ルのように解析されます。
    例:

      FOR /F "usebackq delims==" %i IN (`set`) DO @echo %i

    この例は、現在の環境の環境変数名を列挙します。

また、FOR 変数参照の置換も拡張されました。
次のオプション構文を使うことができます:

    %~I         - すべての引用句 (") を削除して、I を展開します。
    %~fI        - %I を完全修飾パス名に展開します。
    %~dI        - %I をドライブ文字だけに展開します。
    %~pI        - %I をパス名だけに展開します。
    %~nI        - %I をファイル名だけに展開します。
    %~xI        - %I をファイル拡張子だけに展開します。
    %~sI        - 展開されたパスは短い名前だけを含みます。
    %~aI        - %I をファイルの属性に展開します。
    %~tI        - %I ファイルの日付/時刻に展開します。
    %~zI        - %I ファイルのサイズに展開します。
    %~$PATH:I   - PATH 環境変数に指定されているディレクトリを
                  検索し、最初に見つかった完全修飾名に %I を
                  展開します。
                  環境変数名が定義されていない場合、または検索
                  してもファイルが見つからなかった場合は、この
                  修飾子を指定すると空の文字列に展開されます。

修飾子を組み合わせて、複合結果を得ることもできます:

    %~dpI       - %I をドライブ文字とパスだけに展開します。
    %~nxI       - %I をファイル名と拡張子だけに展開します。
    %~fsI       - %I を完全なパスと短い名前だけに展開します。
    %~dp$PATH:I - PATH 環境変数に指定されているディレクトリを
                  検索して %I を探し、最初に見つかったファイル
                  のドライブ文字とパスだけに展開します。
    %~ftzaI     - %I を DIR コマンドの出力行のように展開します。

上の例の %I と PATH は、ほかの有効な値で置き換えることができます。
%~ 構文は、有効な FOR 変数名によって区切られます。%I のような大
文字の変数を使うと読み取りやすく、大文字と小文字を区別しない修飾子
との混乱を避けることができます。

C:\Documents and Settings\hogehoge>

 

(ってか、相変わらずMSDOSのhelpの文章は読みづらいよなぁ…。例が無かったら死ねる。)
 

よって、「for /f」で「skip=n」とすればファイルセットの最初のn個への処理は飛ばせる事になります。
 

また、DIRコマンドでは表示されるファイルリストを目的に従ってソートする事ができます。(普通はファイル名のアルファベット順)

C:\Documents and Settings\hogehoge>help dir
ディレクトリ中のファイルとサブディレクトリを一覧表示します。

DIR [ドライブ:][パス][ファイル名] [/A[[:]属性]] [/B] [/C] [/D] [/L] [/N]
  [/O[[:]ソート順]] [/P] [/Q] [/S] [/T[[:]タイムフィールド]] [/W] [/X] [/4]

  [ドライブ:][パス][ファイル名]
              一覧表示するドライブ、ディレクトリ、またはファイルを指定します。

  /A          指定された属性のファイルを表示します。
  属性         D  ディレクトリ                R  読み取り専用
               H  隠しファイル                A  アーカイブ
               S  システム ファイル           -  その属性以外
  /B          ファイル名のみを表示します (見出しや要約が付きません)。
  /C          ファイル サイズを桁区切り表示します。これは
              既定の設定です。/-C とすると桁区切り表示されません。
  /D          /W と同じですが、ファイルを列で並べ替えた一覧を表示します。
  /L          小文字で表示します。
  /N          ファイル名を右端に表示する一覧形式を使用します。
  /O          ファイルを並べ替えて表示します。
  ソート順    N  名前順 (アルファベット)     S  サイズ順 (小さいほうから)
              E  拡張子順 (アルファベット)   D  日時順 (古いほうから)
              G  グループ (ディレクトリから) -  降順
  /P          1 画面ごとに停止して表示します。
  /Q          ファイルの所有者を表示します。
  /S          指定されたディレクトリおよびそのサブディレクトリのすべての
              ファイルを表示します。
  /T          どのタイムフィールドを表示するか、または並べ替えに使用するかを
              指定します。
  タイムフィールド    C  作成
                      A  最終アクセス
                      W  最終更新
  /W          ワイド一覧形式で表示します。
  /X          このオプションは MS-DOS 形式以外のファイル名に対する短い名前を
              表示します。長い名前の前に短い名前を表示する点を除けば、
              /N オプションと同じです。短い名前がない場合は、ブランクに
              なります。
  /4          4 つの数字で年を表示します。

環境変数 DIRCMD にスイッチを設定できます。
/-W のように - (ハイフン) を前につけると、そのスイッチは無効になります。

C:\Documents and Settings\hogehoge>

よって、「DIR /O-D」で新しい順にファイルのリストが得られます。
 

なので、「新しい順に10個のファイルだけを残す」バッチは以下のようになります。

for /f "skip=10" %%FILE in ('dir /b /o-n') do del %%FILE
  • for /f "skip=n"でfor文の最初n個のアイテムについて処理をskipさせます
  • for文の繰り返し対象の母集団を「dir /b /o-n」の出力結果としています
    • /bはファイル名の他の余分なタイトルとかそういうものの出力を抑止します
    • /o-nで作成日付の降順でソートしています
    • ループで処理中のファイル名は「%FILE」バッチ変数に入っていますが、バッチ内でforを使う時は一時変数名を「%%」で始める必要があります。

また、例えば「*.logのファイルだけを個数制限したい」という場合にはDIRコマンドのオプションの後ろに絞り込み条件を付けます。
 

そしてこのバッチファイルを実行します。
バックアップが行われた後などに定期的に実行されるようにするのが良いでしょう。

履歴

  • 2010/10/18 -- 初版
  • 2012/12/12 -- DIRコマンドのオプションの間違いを修正「/O-N」→「/O-D」

コメント

DIR /O-D の誤り?

こんにちは。
参考にさせていただきました。ありがとうございます。
こちらを参考にされる方はすぐに気付くと思うのですが、一応...
DIR /O-N だと、名前降順になっちゃうので、
日付降順(新しい順)は、DIR /O-D ですよね。

Re:DIR /O-D の誤り?

 訪問ありがとうございます。

あれまぁ、確かに誤ってます。
(元ネタの時にソートしたのがLogファイルで、ファイル名に日付が含まれていたのでそれでも問題なかったからですね^^;)

2年越しのご指摘、感謝です。訂正しておきます。

コメント表示オプション

お好みのコメント表示方法を選び「設定の保存」をクリックすると変更が反映されます。