コマンドプロンプトでforfilesを使ってファイル毎の処理を記述しよう

2019年9月9日

兄「forfilesってコマンドでファイルに対する処理を記述できるんだよ」
妹「ファイル毎の記述って……?」
兄「例えば5個ファイルがあった場合に、それぞれに対して何かのコマンドを使わないといけない時だね」

   FORFILES /P C:\WINDOWS /S /M DNS*.*
    FORFILES /S /M *.txt /C "cmd /c type @file | more"
    FORFILES /P C:\ /S /M *.bat
    FORFILES /D -30 /M *.exe
             /C "cmd /c echo @path 0x09 was changed 30 days ago"
    FORFILES /D 2001/01/01
             /C "cmd /c echo @fname is new since Jan 1st 2001"
    FORFILES /D +2019/8/16 /C "cmd /c echo @fname is new today"
    FORFILES /M *.exe /D +1
    FORFILES /S /M *.doc /C "cmd /c echo @fsize"
    FORFILES /M *.txt /C "cmd /c if @isdir==FALSE notepad.exe @file"

兄「forfilesと入力してそのまま実行すると現在のフォルダーにあるファイルやフォルダーの一覧が表示されるよ」

妹「出てきたね。で、この一覧をどう使うの?これだとdirと変わらない気がするんだけど」

兄「/Sを付ける事でサブフォルダすべてを対象としてファイル一覧を表示させる事ができるよ」
妹「なんだかいっぱい出てきたね。」
兄「他にも/?を見るといろんな検索ができる事がわかるよ」

/P    パス名        検索を開始するパスを示します。
                    既定のフォルダーは現在実行中の
                    ディレクトリ (.) です。

/M    検索マスク    検索マスクによってファイルを検索します。
                    既定の検索マスクは '*' です。

/S                  サブディレクトリに対しても処理を行うように forfiles に
                    指示します (例: "DIR /S")。

/C    コマンド      各ファイルの実行するコマンドを示します。
                    コマンドの文字列は二重引用符で囲んでくだ
                    さい。

                    既定のコマンドは "cmd /c echo @file" です。

                    次の変数をコマンドの文字列に使用することができ
                    ます:
                    @file    - フィルの名前を返します。
                    @fname   - 拡張子なしのファイル名を
                               返します。
                    @ext     - ファイルの拡張子だけを返し
                               ます。
                    @path    - ファイルの完全なパスを返します。
                    @relpath - ファイルの相対パスを返し
                               ます。
                    @isdir   - ファイルの種類がディレクトリの場合
                               は "TRUE"を、ファイルの場合は
                               "FALSE" を返します。
                    @fsize   - ファイルのサイズをバイトで返し
                               ます。
                    @fdate   - ファイルの最終更新日を返し
                               ます。
                    @ftime   - ファイルの最終更新時刻を返し
                               ます。

                    コマンド ラインに特殊文字を使用する場合は、
                    文字を 16 進数コードで 0xHH 形式で (例:
                    タブは 0x09) 指定してください。CMD.EXE の
                    内部コマンドの前には "cmd /c" が必要
                    です。

/D    日付          最終更新日が指定された日かもしくはそれ
                    以降 (+)、または指定された日またはそれ
                    以前 (-) であるファイルを "yyyy/MM/dd" 形式を使っ
                    て選択します。または、最終更新日が現在
                    の日にちより "dd" 日あと、もしくは "dd" 日
                    前であるファイルを選択します。有効な "dd"値は 0 から 32768 の間です。
                    指定がない場合は、"+" が既定で使用されます。
/?                  ヘルプまたは使用法を表示します。
例:
    FORFILES /?
    FORFILES
    FORFILES /P C:\WINDOWS /S /M DNS*.*
    FORFILES /S /M *.txt /C "cmd /c type @file | more"
    FORFILES /P C:\ /S /M *.bat
    FORFILES /D -30 /M *.exe
             /C "cmd /c echo @path 0x09 was changed 30 days ago"
    FORFILES /D 2001/01/01
             /C "cmd /c echo @fname is new since Jan 1st 2001"
    FORFILES /D +2019/8/16 /C "cmd /c echo @fname is new today"
    FORFILES /M *.exe /D +1
    FORFILES /S /M *.doc /C "cmd /c echo @fsize"
    FORFILES /M *.txt /C "cmd /c if @isdir==FALSE notepad.exe @file"

兄「ここでポイントになるのが、/Cオプションだね。コマンドプロンプトで色々なファイルに対する操作を組み込む事ができる。例えば引数でファイル名を受けて処理する自作のCプログラムであったり、組み込みコマンドに与えると、すべての検索で見つかったファイルに対してコマンドを実行する事ができるよ」
妹「できる事が広がるね!」
兄「例えば、数値.txtみたいなファイルをたくさん作って運用する場合に、157から先は1ずつファイル名を足したファイルにして4872.txtまで作る、という時も楽に処理できるよ」
妹「便利だね!お兄ちゃんもそういう事をするの?」
兄「一発物ならエクセルでコマンド書いて作ってペーストする方が楽だからそうするけど、中には運用に組み込まれてて週1で面倒な作業が発生するって時はこれを使う事が多いかな」