69} How do I get the first, or the last, 400 lines of a file?
A question of "head" and "tail" in UNIX terminology. This is a task
that is well suited for
SED or for an
actual head or tail UNIX port.
The first part of this page concerns "head"
The easiest solution is to use
SED
@echo off
sed -n 1,400p myfile.txt
Assume the following LFN-type test file: "My test file.txt"
line 1
line 2 &()[]{}^=;!'+,`~
line 3 <>
line 4
line 6 Line 5 is empty!
line 7
line 8 &()[]{}^=;!'+,`~
line 9
@echo off & setlocal enableextensions
set myfile_=My test file.txt
for /f "tokens=* delims=" %%f in ("%myfile_%") do (
set myfile_=%%~sf)
sed -n 1,6p "%myfile_%"
endlocal & goto :EOF
The output will be
C:\_D\TEST>cmdfaq
line 1
line 2 &()[]{}^=;!'+,`~
line 3 <>
line 4
line 6 Line 5 is empty!
The renaming to a SFN-format is needed when the
SED
version usually assumed in this FAQ is used. However, if the GnuWin32 SED
(let us call it here
UNXSED for distinction)
is used, then the LFN/SFN file name conversion is not needed.
Furthermore, the said collection contains
head
and
tail UNIX ports,
which also could be used in this item.
@echo off & setlocal enableextensions
unxsed 6q "My test file.txt"
endlocal & goto :EOF
The output will be
C:\_D\TEST>cmdfaq
line 1
line 2 &()[]{}^=;!'+,`~
line 3 <>
line 4
line 6 Line 5 is empty!
With GnuWin32
G(nu)AWK from
the solution is
@echo off & setlocal enableextensions
set myfile_=My test file.txt
unxgawk "NR<=6 {printf \"%%s\n\",$0}" "%myfile_%"
endlocal & goto :EOF
A Visual Basic Script (VBScript) aided command line script version
of "head"
@echo off & setlocal enableextensions
::
:: Build a Visual Basic Script
set skip=
set vbs_=%temp%\vhead.vbs
for /f "tokens=*" %%f in ("%vbs_%") do set vbs_=%%~sf
findstr "'%skip%VBS" "%~f0" > %vbs_%
::
:: Run the script with Microsoft Windows Script Host Version 5.6
cscript //nologo %vbs_%
6 < "My test file.txt"
::
:: Clean up
for %%f in (%vbs_%) do del %%f
endlocal & goto :EOF
'
'.......................................................
'The Visual Basic Script for "head"
'
StopAfter=WScript.Arguments.Unnamed(0) 'VBS
i = 0 'VBS
Do While Not WScript.StdIn.AtEndOfStream 'VBS
str = WScript.StdIn.ReadLine 'VBS
i = i + 1 'VBS
If i <= CInt(StopAfter) Then 'VBS
WScript.StdOut.WriteLine str 'VBS
End If 'VBS
Loop 'VBS
The output will again be
C:\_D\TEST>cmdfaq
line 1
line 2 &()[]{}^=;!'+,`~
line 3 <>
line 4
line 6 Line 5 is empty!
Also pure CMD script solutions can be attempted, but they have
limitations with the empty lines and some of the special characters.
Thus for genric purposes these solutions are not recommended.
Getting just the first line
@echo off & setlocal enableextensions
set /p first_=<"My test file.txt"
echo %first_%
endlocal & goto :EOF
The output will be
C:\_D\TEST>cmdfaq
line 1
or
@echo off & setlocal enableextensions
for /f "tokens=* delims=" %%a in (
'type "My test file.txt"') do (
set FirstLine=%%a& goto _ExitForLoop)
:_ExitForLoop
echo FirstLine=%FirstLine%
endlocal & goto :EOF
The output will be
C:\_D\TEST>cmdfaq
FirstLine=line 1
For multiple lines:
@echo off & setlocal enableextensions disabledelayedexpansion
set LineCount=0
for /f "tokens=* delims=" %%r in (
'type "My test file.txt"') do call :EchoLine "%%r"
endlocal & goto :EOF
::
:EchoLine
set /a LineCount+=1
if %LineCount% GTR 6 goto :EOF
echo "%~1"
endlocal & goto :EOF
The output will be
C:\_D\TEST>cmdfaq
"line 1"
"line 2 &()[]{}^^=;!'+,`~"
"line 3 <>"
"line 4"
"line 6 Line 5 is empty!"
"line 7"
which probably is not quite what we want from a useful solution.
The second part of this page concerns "tail"
From a
sed one-liner's
collection by Eric Pement
sed -e :a -e "$q;N;401,$D;ba" myfile.txt
To get the last
six lines (tail -6) of
our test file
@echo off & setlocal enableextensions
unxsed -e :a -e "$q;N;
7,$D;ba" "My test file.txt"
endlocal & goto :EOF
The output will be
C:\_D\TEST>cmdfaq
line 4
line 6 Line 5 is empty!
line 7
line 8 &()[]{}^=;!'+,`~
line 9
Visual Basic Script (VBScript) aided command
line script version of "tail"
@echo off & setlocal enableextensions
::
:: Build a Visual Basic Script
set skip=
set vbs_=%temp%\vtail.vbs
for /f "tokens=*" %%f in ("%vbs_%") do set vbs_=%%~sf
findstr "'%skip%VBS" "%~f0" > %vbs_%
::
:: Run the script with Microsoft Windows Script Host Version 5.6
cscript //nologo %vbs_% "My test file.txt"
6
::
:: Clean up
for %%f in (%vbs_%) do del %%f
endlocal & goto :EOF
'
'.......................................................
'The Visual Basic Script
'
' Define some constants
Const ForReading = 1, ForWriting = 2, ForAppending = 8 'VBS
Dim fileName, FSO, f, i, n, nArg, s 'VBS
'
' Check the right usage
nArg = WScript.Arguments.Count 'VBS
If (nArg = 0) Or (nArg > 2) Then 'VBS
s = "Usage: cscript //nologo " 'VBS
s = s & WScript.ScriptName 'VBS
s = s & " fileName [NumberOfLinesFromEnd]" 'VBS
WScript.Echo s 'VBS
WScript.Quit 'VBS
End If 'VBS
'
' Get the arguments: fileName and tailLines
fileName=WScript.Arguments.Unnamed(0) 'VBS
If WScript.Arguments.Count > 1 Then 'VBS
tailLines = CLng(WScript.Arguments.Unnamed(1)) 'VBS
Else 'VBS
tailLines = 10 'VBS
End If 'VBS
'
' Check that the file exists
Set FSO=CreateObject("Scripting.FileSystemObject") 'VBS
if not FSO.FileExists(fileName) Then 'VBS
WScript.Echo "File " & fileName & " Not Found" 'VBS
WScript.Quit 'VBS
End If 'VBS
'
' Calculate the number of lines
Set f = FSO.OpenTextFile(fileName, ForReading, True) 'VBS
n = 0 'VBS
Do While Not f.AtEndOfStream 'VBS
n = n + 1 'VBS
s = f.ReadLine 'VBS
Loop 'VBS
'
' Output the tail part of the file
Set f = FSO.OpenTextFile(fileName, ForReading, True) 'VBS
i = 0 'VBS
Do While Not f.AtEndOfStream 'VBS
i = i + 1 'VBS
s = f.ReadLine 'VBS
If i > n - tailLines Then WScript.Echo s 'VBS
Loop 'VBS
The output will be
C:\_D\TEST>cmdfaq
line 4
line 6 Line 5 is empty!
line 7
line 8 &()[]{}^=;!'+,`~
line 9
However,
if we are guaranteed an input file
with no blank lines and no poison chracters, then there is a pure CMD
script solution for getting the tail of the file. See
Item #181
for the code.
What about the other way round? Present all but
the first two lines of a text file:
@echo off & setlocal enableextensions
more /e +2 "My test file.txt" > "%temp%\tmp$$$.prn"
type "%temp%\tmp$$$.prn"
if exist "%temp%\tmp$$$.prn" del "%temp%\tmp$$$.prn"
endlocal & goto :EOF
The output will be
C:\_D\TEST>cmdfaq
line 3 <>
line 4
line 6 Line 5 is empty!
line 7
line 8 &()[]{}^=;!'+,`~
line 9
or with sed
@echo off & setlocal enableextensions
unxsed -n 3,$p "My test file.txt"
endlocal & goto :EOF
Getting all but the last line of a file and getting all but (e.g.) the
last three lines of a file are covered in
item #23.