【続々】tailコマンドの作成

前回書いた2つの方法で書いた tail コマンドの基幹部分を示す。
(1) 中間ファイル方式

set I=-%LINE%
set J=0
for /f "delims=" %%A in ('more %1') do (
 set /a J+=1, I+=1
 echo.%%A>%TEMPFILE%
 call set /p SAVE%%J%%=< %TEMPFILE%
 call set "SAVE%%I%%="
)
set /a I+=1
if %I% leq 0 set I=1
setlocal enabledelayedexpansion
for /l %%K in (%I%,1,%J%) do echo.!SAVE%%K!
del /f %TEMPFILE% 2>NUL
goto :eof

(2) for (%%) 方式

set I=-%LINE%
set J=0
for /f "delims=" %%A in ('more %1') do (
 set /a J+=1, I+=1
 for /f "delims=" %%B in ('echo SAVE%%J%%') do set %%B=%%A
 call set "SAVE%%I%%="
)
set /a I+=1
if %I% leq 0 set I=1
setlocal enabledelayedexpansion
for /l %%K in (%I%,1,%J%) do echo.!SAVE%%K!
goto :eof

これと、(3) [続]tailコマンドの作成で書いた、more + を使った方式とで処理時間を比べてみた。テストでは 1000行、約32KB のファイルに対して、tail -10 を行った。結果は、
(1) 25 秒
(2) 99 秒
(3) 1 秒
である。(3) が早いのは当然として、(2)が遅いのはサブシェル起動に時間が掛かっているためと思われる。検証のために、

for /l %I in (1,1,1000) do @cmd /c "@rem"

と、

for /l %I in (1,1,1000) do for /f %J in ('rem') do @echo.

の時間を計ってみると、それぞれ、102秒、75秒である。(2) の結果とも考え合わせると、for /f (' ') によるサブシェル起動は、明示的に cmd を起動するよりは効率よく出来ているようだ。
結論としては、いくら“パイプ入力にも対応”“中間ファイルを使わない”という利点があるとしても(2)は遅すぎる。オペランドでファイルを与えた時は(3)で、そうでない場合は(1)の方式をそれぞれ使うようにするのがいいかと思う。