Extract N lines from file using single windows command - windows

Is there a way to extract/copy the fist X number of lines from a file and input them into another file with a single command using the windows command prompt?
I can delete the first X number of lines using:
more +X [file_containing data] > [file_to_export_data_to]
If the head command would work I think I could just do this:
head -X [file_containing data] > [file_to_export_data_to]
But that unfortunately does not work.
It would be great if Windows had a "less" command but again no luck.
I'm a complete novice when it comes to this stuff so I'm sure I'm missing something obvious. I don't want to install anything or use something other than the command prompt.
Thanks

the simplest one-command solution is to use Powershell Get-Content.
N - number of lines.
From the begining of file:
Get-Content -Head N file.txt
From the end of file:
Get-Content -Tail N file.txt

You can use PowerShell from the cmd.exe console:
powershell -command "& {get-content input.txt|select-object -first 10}" >output.txt
You could create a DOSKEY macro to make it easier to use from the command line:
doskey head=powershell -command "& {get-content $1|select-object -first $2}"
Usage:
head input.txt 10 >output.txt
But you cannot use a DOSKEY macro within a batch script.
You could create a head.bat script instead and place it in a folder that is included in your PATH:
head.bat
#powershell -command "& {get-content %1|select-object -first %2}"
From the command line, you would use head input.txt 10 >output.txt
From within a batch script, you would use call head input.txt 10 >output.txt
I chose not to have the output file as a parameter in case you want to simply display the result to the screen instead of writing to a file.

In order to get correct utf8 output, do the following in powershell
chcp 65001
$OutputEncoding = New-Object -typename System.Text.UTF8Encoding
get-content input.txt -encoding UTF8 |select-object -first 10000 > output.txt
This will get first 10000 lines of input.txt (file in utf8 format) to output.txt with correct encoding.

(#FOR /f "tokens=1* delims=:" %a IN ('findstr /n "^" "standardwaffle.txt"') DO #IF %a leq 7 ECHO(%b)>u:\junk.txt
would extract the first 7 lines of standardwaffle.txt to u:\junk.txt so here it is in one cmd line - but I'd defy you to enter that reliably.
It would also remove any leading : on a source line.
#ECHO OFF
SETLOCAL
IF %1 lss 0 (SET /a line=-%1) ELSE (SET /a line=%1)
FOR /f "tokens=1* delims=:" %%a IN ('findstr /n "^" "%~2"') DO IF %%a leq %line% ECHO(%%b
GOTO :EOF
This batch, saved as head.bat placed anywhere on your path would allow you to use
head -n standardwaffle.txt >junk.txt
to extract the first n lines of standardwaffle.txt to junk.txt
the - would be optional
but this involves installing the batch on your machine. Is that banned by your "no installing" requirement, or is "installing" meant only for 3rd party utilities?

Set Inp = WScript.Stdin
Set Outp = Wscript.Stdout
x = 0
Do Until Inp.AtEndOfStream
x = x + 1
OutP.WriteLine Inp.Readline
If x = 5 then Exit Do
Loop
This prints lines 1 to 5. To use
cscript //nologo <path to script.vbs> <inputfile >outputfile

you can use this:
break>"%temp%\empty"&&fc "%temp%\empty" "%file_to_process%" /lb X /t |more +4 | findstr /B /E /V "*****"
where you should replace the X with the lines you want.Or name this head.bat :
break>"%temp%\empty"&&fc "%temp%\empty" "%file_to_process%" /lb %~1 /t |more +4 | findstr /B /E /V "*****"

If you wanted to stick to simple Windows commands you could use this but would be a little slow for large files ;-) (I've added a second solution below that works better :-) this extracts the last 100 records of any length of file)
find /n " " <test.txt >test.tmp
for /l %%i in (1,1,100) do find "[%%i]" <test.tmp >test.tmp2
for /f "delims=] tokens=2" %%i in (test.tmp2) do echo %%i >>test.new
del test.tmp
del test.tmp2
move /y test.new test.txt
find /v /n "" <test.txt >test.tmp
for /f "delims=: tokens=2 %%i in ('find /v /c "" test.txt') do set /a NR=%%i
set /a NS=%NR%-100
for /l %%i in (%NS%, 1, %NR%) do find "[%%i]" <test.tmp >>test.tmp2
for /f %%i "delims=] tokens=2 %%i in (test.tmp2) do echo %%i >>test.new
move /y test.new test.txt

No need to read whole file; just extract the required lines (head) from beginning of file:
set file=<file>
set line=<required first few lines>
type nul > tmp & fc tmp "%file%" /lb %line% /t | find /v "*****" | more +2
A single line example to extract first 9 lines from file.txt & write into nine.txt
for /f "tokens=* delims=[" %i in ('type "file.txt" ^| find /v /n "" ^| findstr /b /r \[[1-9]\]') do set a=%i& set a=!a:*]=]!& echo:!a:~1!>> nine.txt
Preserves blank lines, lines starting with semicolon, leading spaces and preserves delimiter and whitespaces.
Tested on Win 10 x64 CMD

Related

What is the command in cmd to count words after a particular word?

I am facing the following issue. I am on Windows, using cmd and typing this command findstr "applications" test.txt. The result is something like this:
applications: sample1, guessGame, test1233, testVibeeer, sofiaa
What would be the command to get the number of applications? I have tried with findstr "applications" test.txt | find /c /v "" but it doesn't work. I would like to get a result of 5 in this case but get different result.
try this command.
awk -F "," '{print NF}' test.dat
if you wanna do it in the most awk-ish of minimalist coding, it's
gawk/nawk -F, '$+_=NF++'
mawk/mawk2 -F, 'NF=$_=NF'
use a for /f loop to get the relevant line, then count the tokens after the colon with a pure for loop:
set count=0
for /f "tokens=2 delims=:" %%a in ('find "applications" test.txt') do (
for %%b in (%%a) do set /a count+=1
)
echo %count%
(note, find /c finds lines that contain the search string, so your approach is doomed from the start)
For usage directly on the command line:
set count=0
#for /f "tokens=2 delims=:" %a in ('find "applications" test.txt') do #for %b in (%a) do #set /a count+=1 >nul
echo %count%

How to make a character line across the width of the command line?

How to make a character line across the width of the command line Windows?
In Linux, I can do like this
printf '\n%*s\n\n' \"${COLUMNS:-$(tput cols)}\" '' | tr ' ' -
In Windows, I have so far only
echo -----------------------
you can get the current width of your window with the mode command.
#echo off
setlocal enabledelayedexpansion
"set width="
for /f "tokens=2 delims=:" %%a in ('mode con^|more +4') do if not defined width set /a width=%%a
for /l %%a in (1,1,%width%) do set "line=!line!-"
echo %line%
If you are on a supported version of Windows, this can easily be done using PowerShell. PowerShell also runs on Linux/*NIX and Mac.
powershell -NoLogo -NoProfile -Command "'-' * $Host.UI.RawUI.WindowSize.Width"
I only know a workaround for it by determining the width of the command line window and repeating the character ofter enough.
Since I don't know if you only want it in the command prompt oder in a batch file I post what I made while ago for me. It only works in a batch file or when you save the second part in a batch file and call it in a command prompt window.
:RepeatChar <Char> <Count> <Variable>
setlocal enabledelayedexpansion
set tempRepChar=
for /L %%l in (1,1,%~2) do (
set tempRepChar=!tempRepChar!%~1
)
if /i "%~3"=="" (
echo %tempRepChar%
) else (
set %~3=%tempRepChar%
set tempRepChar=
)
goto :EOF
exit /b
(the extra exit /b in the RepeatChar function isn't really necessary, but I just do it for myself)
You can then call it within a batch file with
for /f %%f in ('powershell.exe -command $host.UI.RawUI.WindowSize.Width') do set WindowsWidth=%%f
call :RepeatChar "-" %WindowsWidth% Stipline
echo %Stripline%
exit /b
if you don't give it the 3rd parameter then it just echos the line so if you only need it once you can just use
call :RepeatChar "-" %WindowsWidth%
Or you can also store or use it via a for loop, like
for /f %%f in ('powershell.exe -command $host.UI.RawUI.WindowSize.Width') do set WindowsWidth=%f
for /f %%f in ('call temp.bat "-" "%WindowsWidth%"') do (
echo %%f
set Stripline=%%f
)

Windows Batch script to read first 10 lines from a 10GB Informatica session log

the for loop in windows batch console hangs and does not work while processing huge files of 10 gb but works with smaller files less than 1 gb. Eg
FOR /F "delims=]" %%A IN (dummy.txt) DO (
...code...
)
I need a batch script that will read first 10 lines of a code from a 10 gb Informatica session log file efficiently. Is there any way to read huge files using batch programming ??
Try this:
#echo off
setlocal EnableDelayedExpansion
rem Read first 10 lines
(for /L %%i in (1,1,10) do set /P "line[%%i]=") < dummy.txt
rem Process them
for /L %%i in (1,1,10) do (
echo Line %%i- !line[%%i]!
FOR /F "delims=]" %%A IN ("!line[%%i]!") DO (
...code...
)
)
PS - I would bet this method run much faster than the PowerShell one! ;)
I suggest you use powershell for this. there are 2 basic methods:
Open powershell. Start, run(search), poweshell.exe. Then cd to the relevant directory and then run:
Get-Content dummy.txt | Select-Object -first 10
or save the above in a file with a .ps1 extenion and simply run it from there.
If you still want to use it from within a batch file, simply make some additions like below and save as a .bat or .cmd file.
powershell -command "& {Get-Content dummy.txt | Select-Object -first 10}"
If you have powershell 3 or later, you can use the new head function built-in.
from batch:
powershell -command "& {Get-Content dummy.txt -Head 10}"
Or again as pure powershell:
Get-Content dummy.txt -Head 10
To read from a huge file you can use a for /F loop and abort it using goto:
#echo off
set /A "COUNT=0, LIMIT=10"
for /F usebackq^ delims^=^ eol^= %%L in ("huge.txt") do (
set /A "COUNT+=1" & set "LINE=%%L"
setlocal EnableDelayedExpansion
rem // Do something with the current line:
echo Line !COUNT!: !LINE!
if !COUNT! geq !LIMIT! goto :QUIT
endlocal
)
:QUIT
The greatest possible length of each line is about 8190 bytes or characters. Empty lines are ignored by for /F and therefore not counted.

Put command output into a variable

Given a directory with the following files
image1.txt
image2.txt
image3.txt
I want to get the oldest file (let the files be sorted by data, oldset date first):
dir /b /od c:\test\image?.txt | findstr ^1
That works great when manually typing it into cmd.exe. Now (in a batch script) I want to put the output of this command in a variable. How can I do this? Thank you!
Update:
Wondering if there is a direct way without usng a loop?
For /F %%A in ('"dir /b /od C:\test\image*.txt|findstr ^1"') do set myVar=%%A
You could do it through For loop, try that in command line, I just tested it and it works fine
Output:
set myVar=image1.txt
On executing Set on command line you can see:
myVar=image1.txt
NUMBER_OF_PROCESSORS=2
There isn't a direct way, the FOR-Loop is one way or the other way is set /p with a temporary file.
dir /b /od c:\test\image?.txt | findstr ^1 > oldest.tmp
< oldest.tmp set /p myVar=
Example:
wmic path Win32_VideoController get CurrentHorizontalResolution | FINDSTR [0-9] > X.txt 'Output in a file
wmic path Win32_VideoController get CurrentVerticalResolution | FINDSTR [0-9] > Y.txt
wmic path Win32_VideoController get CurrentRefreshRate | FINDSTR [0-9] > Hz.txt
wmic path Win32_VideoController get CurrentBitsPerPixel | FINDSTR [0-9] > Bits.txt
set /p X= < X.txt 'Input from a file
set /p Y= < Y.txt
set /p Hz= < Hz.txt
set /p Bits= < Bits.txt
set X=%X: =% 'Remove the spaces
set Y=%Y: =%
set Hz=%Hz: =%
set Bits=%Bits: =%
DEL /q X.txt 'Delete file created
DEL /q Y.txt
DEL /q Hz.txt
DEL /q Bits.txt
Four steps.
set variableName = dir /b /od C;\test\image?.txt | findstr ^1
note: this is untested.
Source:
Google

How to count no of lines in text file and store the value into a variable using batch script?

I want to count the no of lines in a text file and then the value has to be stored into a environment variable. The command to count the no of lines is
findstr /R /N "^" file.txt | find /C ":"
I refered the question How to store the result of a command expression in a variable using bat scripts?
Then I tried,
set cmd="findstr /R /N "^" file.txt | find /C ":" "
I am getting the error message,
FIND: Parameter format not correct
How could i get rid of this error.
There is a much simpler way than all of these other methods.
find /v /c "" filename.ext
Holdover from the legacy MS-DOS days, apparently. More info here: https://devblogs.microsoft.com/oldnewthing/20110825-00/?p=9803
Example use:
adb shell pm list packages | find /v /c ""
If your android device is connected to your PC and you have the android SDK on your path, this prints out the number of apps installed on your device.
You could use the FOR /F loop, to assign the output to a variable.
I use the cmd-variable, so it's not neccessary to escape the pipe or other characters in the cmd-string, as the delayed expansion passes the string "unchanged" to the FOR-Loop.
#echo off
cls
setlocal EnableDelayedExpansion
set "cmd=findstr /R /N "^^" file.txt | find /C ":""
for /f %%a in ('!cmd!') do set number=%%a
echo %number%
Inspired by the previous posts,
a shorter way of doing so:
CMD.exe
C:\>FINDSTR /R /N "^.*$" file.txt | FIND /C ":"
The number of lines
Try it. It works in my console.
EDITED:
(the "$" sign removed)
FINDSTR /R /N "^.*" file.txt | FIND /C ":"
$ reduces the number by 1 because it is accepting the first row as Field name and then counting the number of rows.
Try this:
#Echo off
Set _File=file.txt
Set /a _Lines=0
For /f %%j in ('Find "" /v /c ^< %_File%') Do Set /a _Lines=%%j
Echo %_File% has %_Lines% lines.
It eliminates the extra FindStr and doesn't need expansion.
- edited to use ChrisJJ's redirect suggestion. Removal of the TYPE command makes it three times faster.
#Tony: You can even get rid of the type %file% command.
for /f "tokens=2 delims=:" %%a in ('find /c /v "" %_file%') do set /a _Lines=%%a
For long files this should be even quicker.
I usually use something more like this
for /f %%a in (%_file%) do (set /a Lines+=1)
for /f "usebackq" %A in (`TYPE c:\temp\file.txt ^| find /v /c "" `) do set numlines=%A
in a batch file, use %%A instead of %A
The perfect solution is:
FOR /F %%i IN ('TYPE "Text file.txt" ^| FIND /C /V ""') DO SET Lines=%%i
I found this solution to work best for creating a log file that maintains itself:
setlocal enabledelayedexpansion
SET /A maxlines= 10
set "cmd=findstr /R /N "^^" "filename.txt" | find /C ":""
for /f %%a in ('!cmd!') do set linecount=%%a
GOTO NEXT
:NEXT
FOR /F %%A IN ("filename.txt") DO (
IF %linecount% GEQ %maxlines% GOTO ExitLoop
echo %clientname% %Date% %Time% >> "filename.txt")
EXIT
:ExitLoop
echo %clientname% %Date% %Time% > "filename.txt"
EXIT
Environmental variables included are %clientname% the computername of the remote client %Date% is the current date and %Time% the current time. :NEXT is called after getting the number of lines in the file. If the file line count is greater than the %maxlines% variable it goes to the :EXITLOOP where it overwrites the file, creating a new one with the first line of information. if it is less than the %maxlines% variable it simply adds the line to the current file.
You don't need to use find.
#echo off
set /a counter=0
for /f %%a in (filename) do set /a counter+=1
echo Number of lines: %counter%
This iterates all lines in the file and increases the counter variable by 1 for each line.
The :countLines subroutine below accepts two parameters: a variable name; and a filename. The number of lines in the file are counted, the result is stored in the variable, and the result is passed back to the main program.
The code has the following features:
Reads files with Windows or Unix line endings.
Handles Unicode as well as ANSI/ASCII text files.
Copes with extremely long lines.
Isn’t fazed by the null character.
Raises an error on reading an empty file.
Counts beyond the Batch max int limit of (31^2)-1.
#echo off & setLocal enableExtensions disableDelayedExpansion
call :countLines noOfLines "%~1" || (
>&2 echo(file "%~nx1" is empty & goto end
) %= cond exec =%
echo(file "%~nx1" has %noOfLines% line(s)
:end - exit program with appropriate errorLevel
endLocal & goto :EOF
:countLines result= "%file%"
:: counts the number of lines in a file
setLocal disableDelayedExpansion
(set "lc=0" & call)
for /f "delims=:" %%N in ('
cmd /d /a /c type "%~2" ^^^& ^<nul set /p "=#" ^| (^
2^>nul findStr /n "^" ^&^& echo(^) ^| ^
findStr /blv 1: ^| 2^>nul findStr /lnxc:" "
') do (set "lc=%%N" & call;) %= for /f =%
endlocal & set "%1=%lc%"
exit /b %errorLevel% %= countLines =%
I know it looks hideous, but it covers most edge-cases and is surprisingly fast.
Just:
c:\>(for /r %f in (*.java) do #type %f ) | find /c /v ""
Font: https://superuser.com/questions/959036/what-is-the-windows-equivalent-of-wc-l
One nice surprise is for one who has git bash on his windows: just plain old linux wc -l <filename> will works for you there
In the below code, the variable name are SalaryCount and TaxCount
#ECHO OFF
echo Process started, please wait...
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Salary.txt"') do set SalaryCount=%%C
echo Salary,%SalaryCount%
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Tax.txt"') do set TaxCount=%%C
echo Tax,%TaxCount%
Now if you need to output these values to a csv file, you could use the below code.
#ECHO OFF
cd "D:\CSVOutputPath\"
echo Process started, please wait...
echo FILENAME,FILECOUNT> SUMMARY.csv
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Salary.txt"') do set Count=%%C
echo Salary,%Count%>> SUMMARY.csv
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Tax.txt"') do set Count=%%C
echo Tax,%Count%>> SUMMARY.csv
The > will overwrite the existing content of the file and the >> will append the new data to existing data. The CSV will be generated in D:\CSVOutputPath
You can pipe the output of type into find inside the in(…) clause of a for /f loop:
for /f %%A in ('
type "%~dpf1" ^| find /c /v ""
') do set "lineCount=%%A"
But the pipe starts a subshell, which slows things down.
Or, you could redirect input from the file into find like so:
for /f %%A in ('
find /c /v "" ^< "%~dpf1"
') do set "lineCount=%%A"
But this approach will give you an answer 1 less than the actual number of lines if the file ends with one or more blank lines, as teased out by the late foxidrive in counting lines in a file.
And then again, you could always try:
find /c /v "" example.txt
The trouble is, the output from the above command looks like this:
---------- EXAMPLE.TXT: 511
You could split the string on the colon to get the count, but there might be more than one colon if the filename had a full path.
Here’s my take on that problem:
for /f "delims=" %%A in ('
find /c /v "" "%~1"
') do for %%B in (%%A) do set "lineCount=%%B"
This will always store the count in the variable.
Just one last little problem… find treats null characters as newlines. So if sneaky nulls crept into your text file, or if you want to count the lines in a Unicode file, this answer isn’t for you.
You can also try
set n=0 & for /f "tokens=*" %a in (text.txt) do set/a n=!n!+1
echo !n!
You can also mark with a wildcard symbol * to facilitate group files to count.
Z:\SQLData>find /c /v "" FR_OP133_OCCURENCES_COUNT_PER_DOCUMENTS_*.txt
Result
---------- FR_OP133_OCCURENCES_COUNT_PER_DOCUMENTS_AVIFRS01_V1.TXT: 2041
---------- FR_OP133_OCCURENCES_COUNT_PER_DOCUMENTS_AVIOST00_V1.TXT: 315938
---------- FR_OP133_OCCURENCES_COUNT_PER_DOCUMENTS_AVIFRS00_V1.TXT: 0
---------- FR_OP133_OCCURENCES_COUNT_PER_DOCUMENTS_CNTPTF00_V1.TXT: 277

Resources