30

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

dbenham
  • 127,446
  • 28
  • 251
  • 390
user1769292
  • 309
  • 1
  • 3
  • 4

8 Answers8

45

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
Janusz
  • 1,343
  • 11
  • 16
  • 2
    I get "A parameter cannot be found that matches parameter name 'Head'." error. – Pavel Chuchuva Jul 14 '16 at 03:43
  • Check version of PowerShell, I assume it is old. Or a typo somewhere in the command. – Janusz Apr 25 '17 at 08:30
  • 2
    You may have to use 'TotalCount' instead of 'Head'. See https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-content?view=powershell-6 – EstevaoLuis Jul 03 '18 at 07:53
  • Add ` > tagetfile.txt` at the end of the command, to pipe into a file instead of just displaying. – FlorianH Jul 19 '21 at 16:37
26

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.

dbenham
  • 127,446
  • 28
  • 251
  • 390
4

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.

sdk
  • 51
  • 2
2
(@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?

Magoo
  • 77,302
  • 8
  • 62
  • 84
  • The batch file appears to read the whole file first, as in a file of 500Mb it is taking a lot, and in small files it works instantly. On the other hand, the solution with Powershell by dbenham appears to output the intended part fast, so it can be interrupted while it is still reading the rest of the file. – sancho.s ReinstateMonicaCellio Apr 09 '16 at 10:46
  • 1
    I was hoping for a batch/cmd solution too, but I've got a 25GiB file to work with. Definitely don't want it trying to read that into memory. :/ – shawn Apr 06 '19 at 05:15
1
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
Chris J
  • 7,549
  • 2
  • 25
  • 25
Serenity
  • 433
  • 2
  • 4
1

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 "*****"
npocmaka
  • 55,367
  • 18
  • 148
  • 187
0

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
  • You are right - this is sloow `:)`. Shouldn't it be `>>` in the second line? You should also mention where to insert "Startline" and "Endline" (to me it's obvious, but without some experience, it's hard to tell) – Stephan Mar 26 '19 at 13:28
  • Yes you're right, sorry my bad (typo) and yes I assumed it would be obvious that 1 and 100 are the start and end lines, you could vary them to extract any portion of the file you wanted on a line number basis. – Chris Clews Mar 26 '19 at 13:53
  • Mind expanding your answer to make it a good one? (and it's `cmd`, not `DOS`. Your code wouldn't run in `DOS`) – Stephan Mar 27 '19 at 09:39
-1

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

Zimba
  • 2,854
  • 18
  • 26