2

There is such a shell command in the chapter "transformational programming" of "The Pragmatic Programmer".

Its function is to list the five files with the most lines in the current directory.

$ find . -type f | xargs wc -l | sort -n | tail -6 | head -5
     470 ./debug.pml
     470 ./test_to_build.pml
     487 ./dbc.pml
     719 ./domain_languages.pml
     727 ./dry.pml

I'm trying to do the same thing with PowerShell,But it seems too wordy

(Get-ChildItem .\ | ForEach-Object {$_ | Select-Object -Property 'Name', @{label = 'Lines'; expression = {($_ | Get-Content).Length}}} |Sort-Object -Property 'Lines')|Select-Object -Last 5

I believe there will be a simpler way, but I can't think of it.

How to get files with most lines in the current directory by simplest way using PowerShell?

Of course, you don't need to use custom aliases and abbreviations to shorten the length. Although it looks more concise, it loses readability.

Andy
  • 1,077
  • 1
  • 8
  • 20
  • 1
    the following shows ways to get the line count of a text file ... PowerShell get number of lines of big (large) file - >>> Stack Overflow — https://stackoverflow.com/questions/12084642/powershell-get-number-of-lines-of-big-large-file <<< once you have that, you can sort by the line count and grab the ones you want. [*grin*] – Lee_Dailey Jan 09 '21 at 09:42

4 Answers4

2
Get-Content * | Group-Object PSChildName | Select-Object Count, Name |
    Sort-Object Count | Select-Object -Last 5
iRon
  • 20,463
  • 10
  • 53
  • 79
  • Interesting, I didn't know that `Get-Content` adds properties such as `PSChildName` from its input object(s) to its output. This seems to be missing from the documentation. – zett42 Jan 09 '21 at 20:35
1

I finally found my own satisfactory answer!

Used 3 pipeline operators, shell used 5!

What's more, what we get is the object, which can be used for more extensible operations.

I feel better than shell of linux.

dir -file | sort {($_ | gc).Length} | select -l 5
Andy
  • 1,077
  • 1
  • 8
  • 20
  • 1
    But keep in mind that the performance is really slow compared to ```[System.IO.File]::ReadLines``` (see my answer below). Especially when counting lines of bigger files. In my test environment: ```File.ReadLines = 2.7 seconds``` vs. ```Get-Content = 31.56 seconds``` – swbbl Jan 12 '21 at 18:42
  • @pwnosh Thank you for reminding me,that when performance is required, we should use C #, not cmdlet. But,how efficient is 'get-content' compared to the Shell?I'm very curious, but I can't test it because I don't understand liunx at all. – Andy Jan 12 '21 at 23:15
  • Not exactly. You don't need C# signatures or compiled projects. In PowerShell (Windows & Core) you can make use of every .NET Framework & Core classes (.NET is the underlying Framework of PowerShell, C#, F#, etc). You can use e.g. ```[System.IO.File]::Exists('C:\temp\test.log')``` directly in PowerShell. (Or did I misunderstand your question?) – swbbl Jan 13 '21 at 05:05
  • @pwnosh Thank you for your supplement. In fact, I understand this. This is not easy to describe, so it is easy to cause misunderstanding. – Andy Jan 13 '21 at 06:36
0

Try either File.ReadLines with Linq or File.ReadAllLines with Count property.

File.ReadLines

Get-ChildItem .\ -File | 
    Select-Object -Property Name, @{n='Lines'; e= { 
            [System.Linq.Enumerable]::Count([System.IO.File]::ReadLines($_.FullName)) 
        } 
    } | Sort-Object -Property 'Lines' -Descending | Select-Object -First 5

File.ReadAllLines

Get-ChildItem .\ -File | 
    Select-Object -Property Name, @{n='Lines'; e= { 
            [System.IO.File]::ReadAllLines($_.FullName).Count 
        } 
    } | Sort-Object -Property 'Lines' -Descending | Select-Object -First 5
swbbl
  • 814
  • 1
  • 4
  • 10
0

A fast approach would be to use switch -File:

$files = (Get-ChildItem -File ).FullName 
$result = foreach ($file in $files) {
    $lineCount = 0
    switch -File $file {
        default { $lineCount++ }
    }
    [PsCustomObject]@{
        File  = $file
        Lines = $lineCount
    }
}
$result | Sort-Object Lines | Select-Object -Last 5
Theo
  • 57,719
  • 8
  • 24
  • 41