164

On windows, using Powershell, what are the equivalent commands to linux's head, tail, more, less and sed?

Codebling
  • 10,764
  • 2
  • 38
  • 66
Yue Zhang
  • 1,829
  • 2
  • 12
  • 9
  • log file is too big, about several MBytes. It's too hard to view by notepad.exe. – Yue Zhang Mar 13 '12 at 10:16
  • 1
    If you are using `notepad` as your base I would suggest looking at alternative text editors, there are plenty of (both free and paid) alternatives. All are superior to notepad (albeit that's not much of a challenge). – Richard Mar 13 '12 at 11:34
  • possible duplicate of [PowerShell vs. Unix Shells](http://stackoverflow.com/questions/573623/powershell-vs-unix-shells) – manojlds Mar 13 '12 at 16:17
  • I deal with large files and I use/install Vim which proves much faster than any other tool I have used. – sfanjoy Aug 13 '18 at 19:30

7 Answers7

259

Get-Content (alias: gc) is your usual option for reading a text file. You can then filter further:

gc log.txt | select -first 10 # head
gc -TotalCount 10 log.txt     # also head
gc log.txt | select -last 10  # tail
gc -Tail 10 log.txt           # also tail (since PSv3), also much faster than above option
gc log.txt | more             # or less if you have it installed
gc log.txt | %{ $_ -replace '\d+', '($0)' }         # sed

This works well enough for small files, larger ones (more than a few MiB) are probably a bit slow.

The PowerShell Community Extensions include some cmdlets for specialised file stuff (e.g. Get-FileTail).

Joey
  • 344,408
  • 85
  • 689
  • 683
  • 4
    Holy cow, this is maxing out my CPU to do a `-last 2` on a 1GB CSV. Hot beverage: ☕ – mlissner Feb 19 '13 at 19:28
  • 14
    @mlissner: If you're on PowerShell v3 you can use `Get-Content -Tail 2` instead. That's definitely faster. – Joey Feb 20 '13 at 07:56
  • 1
    `gc log.txt | %{ $_ -replace '\d+', '($0)' } # sed` that is not actually fully the sed tool as it does not put content back. It needs Set-Content. – Artyom Jun 15 '15 at 13:24
  • @Artem: And parentheses in that case. I wasn't aware that sed writes anything by itself; I've seen it used mostly to change stuff in a stream. – Joey Jun 15 '15 at 13:46
  • wow, -last is slow! also, why didn't they just make a command called `head`? – Neil McGuigan Mar 30 '16 at 23:01
  • 4
    @Neil, `-Last` is slow for the same reason `awk` would be slow for the same task: It has to consume the stream completely first. That's why `Get-Content -Tail` exists. And there is no `head` because it doesn't fit into the naming conventions, and its purpose is already served by `Select-Item`. – Joey Mar 31 '16 at 04:52
  • 3
    @neil @joey They have an alias for `-head`. See my answer http://stackoverflow.com/a/41626586/1081043 – wisbucky Jan 13 '17 at 02:44
  • @wisbucky: That's a parameter alias for `-TotalCount`, not a command alias for `Get-Content`. I was referring to commands here, as was Neil. – Joey Jan 13 '17 at 08:08
  • can you update your example where you pipe it into a new file ? – Areza Jan 11 '19 at 09:48
  • @user702846: `Out-File`. – Joey Jan 11 '19 at 10:20
  • New home for [PowerShell Community Extensions](https://github.com/Pscx/Pscx) – CFreitas Apr 06 '21 at 10:05
89

Here are the built-in ways to do head and tail. Don't use pipes because if you have a large file, it will be extremely slow. Using these built-in options will be extremely fast even for huge files.

gc log.txt -head 10 
gc log.txt -tail 10
gc log.txt -tail 10 -wait # equivalent to tail -f
wisbucky
  • 33,218
  • 10
  • 150
  • 101
  • but [Joey's comment](https://stackoverflow.com/questions/9682024/how-to-do-what-head-tail-more-less-sed-do-in-powershell#comment60271566_9682594) seems to indicate the exact opposite! how do I know who to trust or which (built-in) method is most efficient? – NH. Sep 22 '17 at 18:53
  • 2
    @NH My answer is in agreement with Joey's comment. His comment says "-Last is slow... That's why Get-Content -Tail exists." `| select -last` uses pipes. I'm using `-tail` without pipes. But if you do ever find two conflicting answers, you could probably trust the person with a much higher reputation. Also, you can simply try the two methods on a large file. It will be very obvious on a large file. – wisbucky Sep 25 '17 at 04:32
  • I also discovered Select-Object, which you can then alias as "grep" :) – Patrick Burwell Feb 11 '21 at 20:58
  • Noting that `-Head` and `-First` are aliases for `-TotalCount` – Jason S Nov 16 '21 at 21:53
9

more.exe exists on Windows, ports of less are easily found (and the PowerShell Community Extensions, PSCX, includes one).

PowerShell doesn't really provide any alternative to separate programs for either, but for structured data Out-Grid can be helpful.

Head and Tail can both be emulated with Select-Object using the -First and -Last parameters respectively.

Sed functions are all available but structured rather differently. The filtering options are available in Where-Object (or via Foreach-Object and some state for ranges). Other, transforming, operations can be done with Select-Object and Foreach-Object.

However as PowerShell passes (.NET) objects – with all their typed structure, eg. dates remain DateTime instances – rather than just strings, which each command needs to parse itself, much of sed and other such programs are redundant.

Richard
  • 106,783
  • 21
  • 203
  • 265
  • 1
    Brilliant. gc does not seem to support pipe input. when I want to filter a command's output, I am using "...exe ...|select-object -first 20|select-object -last 1" – A117 Nov 28 '18 at 02:04
3

"-TotalCount" in this instance responds exactly like "-head". You have to use -TotalCount or -head to run the command like that. But -TotalCount is misleading - it does not work in ACTUALLY giving you ANY counts...

gc -TotalCount 25 C:\scripts\logs\robocopy_report.txt

The above script, tested in PS 5.1 is the SAME response as below...

gc -head 25 C:\scripts\logs\robocopy_report.txt

So then just use '-head 25" already!

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
Patrick Burwell
  • 129
  • 1
  • 12
  • 1
    `-TotalCount` behaviour is as documented. Behaves like Unix `head` https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-content?view=powershell-5.1 "Specifies the number of lines from the beginning of a file or other item. The default is -1 (all lines). You can use the TotalCount parameter name or its aliases, First or Head." – Jason S Nov 16 '21 at 21:55
2

If you need to query large (or small) log files on Windows, the best tool I have found is Microsoft's free Log Parser 2.2. You can call it from PowerShell if you want and it will do all the heavy lifting for you, and very fast too.

What Would Be Cool
  • 6,204
  • 5
  • 45
  • 42
0

I got some better solutions:

gc log.txt -ReadCount 5 | %{$_;throw "pipeline end!"} # head
gc log.txt | %{$num=0;}{$num++;"$num $_"}             # cat -n
gc log.txt | %{$num=0;}{$num++; if($num -gt 2 -and $num -lt 7){"$num $_"}} # sed
Yue Zhang
  • 1,829
  • 2
  • 12
  • 9
-1
$Push_Pop = $ErrorActionPreference #Suppresses errors
$ErrorActionPreference = “SilentlyContinue” #Suppresses errors
#Script
    #gc .\output\*.csv -ReadCount 5 | %{$_;throw "pipeline end!"} # head
    #gc .\output\*.csv | %{$num=0;}{$num++;"$num $_"}             # cat -n
    gc .\output\*.csv | %{$num=0;}{$num++; if($num -gt 2 -and $num -lt 7){"$num $_"}} # sed
#End Script 
$ErrorActionPreference = $Push_Pop #Suppresses errors

You don't get all the errors with the pushpop code BTW, your code only works with the "sed" option. All the rest ignores anything but gc and path.

Patrick Burwell
  • 129
  • 1
  • 12
  • This does suppress errroractionpreference... I use this in my $profile all the time... 'ErrorActionPreference = “SilentlyContinue” #Suppresses errors' – Patrick Burwell Sep 27 '21 at 17:07