【続】tailコマンドの作成

昨日の head コマンドだが、第一パラメータで、+10 とか /E 等の more の有効なオプションを指定してしまうと、第二パラメータにファイル名を指定しても無視され標準入力待ちになってしまう。とりあえず、

set "OPT=%~1"
if "%OPT:~0,1%"=="/" echo>&2 コマンドの構文が誤っています&exit /b 1
if "%OPT:~0,1%"=="+" echo>&2 コマンドの構文が誤っています&exit /b 1

を追加しておく。

tail コマンドだが、ファイルからの読み込みに限定すると別の解法がある。まず、find /c /v "" < file 等でファイル全体の行数を求め、表示行数を引いて、何行目以降を表示するか決める。以前考えた時には、find で求められるのは空行も含めた全体行数で、for /f では空行が飛ぶので行数が合わないと思っていた。しかし、for /fskip= オプションを使うと、空行も含めた行数で先頭から読み飛ばすことが出来る。

@echo off
setlocal
if not defined LINE set LINE=20
set "OPT=%~1"
if not defined OPT echo>&2 コマンドの構文が誤っています&exit /b 1
if "%OPT:~0,1%"=="/" echo>&2 コマンドの構文が誤っています&exit /b 1
if "%OPT:~0,1%"=="+" echo>&2 コマンドの構文が誤っています&exit /b 1
set OPT=0
set /a "OPT=%~1" 2>NUL >NUL
if %OPT% lss 0 set /a LINE=-OPT&shift /1 
for /f %%N in ('find /c /v "" ^< %1') do set N=%%N
set /a L=N-LINE
if %L% gtr 0 (set S=skip=%L%) else (set S=)
for /f "%S% delims=" %%A in ('more %1') do echo.%%A

どうせ more を使うんだったら、最後の2行は、

if %L% lss 0 set L=0
more +%L% %1

でいいか。何のことは無い簡単なスクリプトになった。しかも速い。

しかし、これらでは標準入力を扱うことは出来ない。せっかく head コマンドが標準入力対応に出来たので、前回のような環境変数に覚えておく方式の for /f 版を引き続き考える。