Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursively count files in subfolders

I am trying to count the files in all subfolders in a directory and display them in a list.

For instance the following dirtree:

TEST
    /VOL01
        file.txt
        file.pic
    /VOL02
        /VOL0201
            file.nu
            /VOL020101
                file.jpg
                file.erp
                file.gif
    /VOL03
        /VOL0301
            file.org

Should give as output:

PS> DirX C:\TEST

Directory              Count
----------------------------
VOL01                      2
VOL02                      0
VOL02/VOL0201              1
VOL02/VOL0201/VOL020101    3
VOL03                      0
VOL03/VOL0301              1

I started with the following:

Function DirX($directory)
{
    foreach ($file in Get-ChildItem $directory -Recurse)
    {
        Write-Host $file
    }
}

Now I have a question: why is my Function not recursing?

like image 916
Pr0no Avatar asked Aug 26 '14 13:08

Pr0no


People also ask

How do I count files in a folder and subfolders?

Use File Explorer Open the folder and select all the subfolders or files either manually or by pressing CTRL+A shortcut. If you choose manually, you can select and omit particular files. You can now see the total count near the left bottom of the window. Repeat the same for the files inside a folder and subfolder too.

How do I count files in current directory recursively?

To determine how many files there are in the current directory, put in ls -1 | wc -l . This uses wc to do a count of the number of lines (-l) in the output of ls -1 .

How do I count the number of files in multiple folders?

Browse to the folder containing the files you want to count. Highlight one of the files in that folder and press the keyboard shortcut Ctrl + A to highlight all files and folders in that folder. In the Explorer status bar, you'll see how many files and folders are highlighted, as shown in the picture below.

How do I count the number of files in a directory?

To determine how many files there are in the current directory, put in ls -1 | wc -l. This uses wc to do a count of the number of lines (-l) in the output of ls -1.


3 Answers

Something like this should work:

dir -recurse |  ?{ $_.PSIsContainer } | %{ Write-Host $_.FullName (dir $_.FullName | Measure-Object).Count }
  • dir -recurse lists all files under current directory and pipes (|) the result to
  • ?{ $_.PSIsContainer } which filters directories only then pipes again the resulting list to
  • %{ Write-Host $_.FullName (dir $_.FullName | Measure-Object).Count } which is a foreach loop that, for each member of the list ($_) displays the full name and the result of the following expression
  • (dir $_.FullName | Measure-Object).Count which provides a list of files under the $_.FullName path and counts members through Measure-Object

  • ?{ ... } is an alias for Where-Object

  • %{ ... } is an alias for foreach
like image 134
David Brabant Avatar answered Oct 21 '22 06:10

David Brabant


Similar to David's solution this will work in Powershell v3.0 and does not uses aliases in case someone is not familiar with them

Get-ChildItem -Directory | ForEach-Object { Write-Host $_.FullName $(Get-ChildItem $_ | Measure-Object).Count}

Answer Supplement

Based on a comment about keeping with your function and loop structure i provide the following. Note: I do not condone this solution as it is ugly and the built in cmdlets handle this very well. However I like to help so here is an update of your script.

Function DirX($directory)
{
    $output = @{}

    foreach ($singleDirectory in (Get-ChildItem $directory -Recurse -Directory))
    {
        $count = 0 
        foreach($singleFile in Get-ChildItem $singleDirectory.FullName)
        {
            $count++
        }
        $output.Add($singleDirectory.FullName,$count)
    }

    $output | Out-String
}

For each $singleDirectory count all files using $count ( which gets reset before the next sub loop ) and output each finding to a hash table. At the end output the hashtable as a string. In your question you looked like you wanted an object output instead of straight text.

like image 9
Matt Avatar answered Oct 21 '22 04:10

Matt


Well, the way you are doing it the entire Get-ChildItem cmdlet needs to complete before the foreach loop can begin iterating. Are you sure you're waiting long enough? If you run that against very large directories (like C:) it is going to take a pretty long time.

Edit: saw you asked earlier for a way to make your function do what you are asking, here you go.

Function DirX($directory)
{
    foreach ($file in Get-ChildItem $directory -Recurse -Directory )
    {
        [pscustomobject] @{
        'Directory' = $File.FullName
        'Count' = (GCI $File.FullName -Recurse).Count
        }
    }
}
DirX D:\

The foreach loop only get's directories since that is all we care about, then inside of the loop a custom object is created for each iteration with the full path of the folder and the count of the items inside of the folder.

Also, please note that this will only work in PowerShell 3.0 or newer, since the -directory parameter did not exist in 2.0

like image 3
Noah Sparks Avatar answered Oct 21 '22 06:10

Noah Sparks