I read this question very often on different blogs and mostly is the answere a „Get-Childitem“ command. This achieves its goal, but with a large file system you soon reach its limits because the command takes a long time.
However, there is a simple and faster alternative that I have been using for several years.
I have already described this in my (german) article „Multitool Robocopy„, in this article I would like to go into more detail.
What ist robocopy?
First of all Robocopy is a copy tool that allows you to transfer data from A to B faster than the normal windows copy process. Robocopy also offers other features that are appreciated by administrators.
Examples are
- mirror a dataset from folder A to folder B
- ability to tolerate network interruptions
- skip files already in the destination folder
- copy paths exceeding 259 characters
- and many more
So Robocopy is a fast copy program, but how does a copy tool help me now with an evaluation of files and folders?
How does it work?
Robocopy displays at the end of a operation a tabular overview of all copied files, folders and the number of copied bytes.
We can use this table to create our file/folder count evaluation.
In order not to have to copy files to get this table, we can specify the „/l“ parameter in our robocopy commad. This parameter specifies that the files should only be listed (and not copied, deleted or timestamped). This means that we do not perform a copy operation, but still get the desired output.
the command
With this command you get the addressed table without performing a copy operation.
$dir = "C:\Temp"
robocopy /l /nfl /ndl $dir \localhost\C$\nul /e /bytes
the function
To make the output usable with Powershell I created the following function.
function Get-DirItemCount {
param (
[Parameter(Mandatory=$true)]
[string]$path
)
robocopy /l /nfl /ndl $path \\localhost\C$\nul /e /bytes | ?{
$_ -match "^[ \t]+(Dirs|Files|Bytes) :[ ]+\d"
} | %{
$line = $_.Trim() -replace '[ ]{2,}',',' -replace ' :',':'
$value = $line.split(',')[1]
if ($line -match "Dirs:" ){
$dirCount = $value
}
if ($line -match "Files:" ){
$fileCount = $value
}
if ($line -match "Bytes:" ){
$value = $line.split(' ')[1]
$Bytes = $value
}
}
[pscustomobject]@{Path=$path;Directories=$dirCount;Files=$fileCount;Bytes=$Bytes}
}
Get-DirItemCount "C:\Temp"
Path Directories Files Bytes
---- ----------- ----- -----
C:\Temp 21 153 6478742645
Info: If you don’t use english as operating system language you have to change the values „Dirs|Files|Bytes“ in line 7.
For german it is „Verzeich.|Dateien|Bytes“