I have found several resources that use the following script to get folder sizes
$colItems = (Get-ChildItem $startFolder -recurse | Where-Object {$_.PSIsContainer -eq $True} | Sort-Object)
foreach ($i in $colItems)
{
$subFolderItems = (Get-ChildItem $i.FullName | Measure-Object -property length -sum)
$i.FullName + " -- " + "{0:N2}" -f ($subFolderItems.sum / 1MB) + " MB"
}
The problem with that is it also lists the subdirectories ie:
c:\test\1 -- 10mb
c:\test\1\folder -- 10mb
c:\test\1\folder\deep -- 5mb
c:\test\1\folder\tuna -- 5mb
c:\test\2 -- 20bm
c:\test\2\folder -- 20mb
c:\test\2\folder\deep -- 10mb
c:\test\2\folder\tuna -- 10mb
I think you know see where I am going. What I am looking for is just the parent folder's results... SO:
c:\test\1 -- 10mb
c:\test\2 -- 20mb
How can this be accomplished with Powershell?
....
You need to get the total contents size of each directory recursively to output. Also, you need to specify that the contents you're grabbing to measure are not directories, or you risk errors (as directories do not have a Length parameter).
Here's your script modified for the output you're looking for:
$colItems = Get-ChildItem $startFolder | Where-Object {$_.PSIsContainer -eq $true} | Sort-Object
foreach ($i in $colItems)
{
$subFolderItems = Get-ChildItem $i.FullName -recurse -force | Where-Object {$_.PSIsContainer -eq $false} | Measure-Object -property Length -sum | Select-Object Sum
$i.FullName + " -- " + "{0:N2}" -f ($subFolderItems.sum / 1MB) + " MB"
}
This simple solution worked for me as well.
Get-ChildItem -Recurse 'directory_path' | Measure-Object -Property Length -Sum
The solution posted by #Linga:
"Get-ChildItem -Recurse 'directory_path' | Measure-Object -Property Length -Sum" is nice and short. However, it only computes the size of 'directory_path', without sub-directories.
Here is a simple solution for listing all sub-directory sizes. With a little pretty-printing added.
(Note: use the -File option to avoid errors for empty sub-directories)
foreach ($d in gci -Directory -Force) {
'{0,15:N0}' -f ((gci $d -File -Recurse -Force | measure length -sum).sum) + "`t`t$d"
}
Sorry to reanimate a dead thread, but I have just been dealing with this myself, and after finding all sorts of crazy bloated solutions, I managed to come up with this.
[Long]$actualSize = 0
foreach ($item in (Get-ChildItem $path -recurse | Where {-not $_.PSIsContainer} | ForEach-Object {$_.FullName})) {
$actualSize += (Get-Item $item).length
}
Quickly and in few lines of code gives me a folder size in Bytes, than can easily be converted to any units you want with / 1MB or the like.
Am I missing something? Compared to this overwrought mess it seems rather simple and to the point. Not to mention that code doesn't even work since the called function is not the same name as the defined function. And has been wrong for 6 years. ;)
So, any reasons NOT to use this stripped down approach?
This is similar to https://stackoverflow.com/users/3396598/kohlbrr answer, but I was trying to get the total size of a single folder and found that the script doesn't count the files in the Root of the folder you are searching. This worked for me.
$startFolder = "C:\Users";
$totalSize = 0;
$colItems = Get-ChildItem $startFolder
foreach ($i in $colItems)
{
$subFolderItems = Get-ChildItem $i.FullName -recurse -force | Where-Object {$_.PSIsContainer -eq $false} | Measure-Object -property Length -sum | Select-Object Sum
$totalSize = $totalSize + $subFolderItems.sum / 1MB
}
$startFolder + " | " + "{0:N2}" -f ($totalSize) + " MB"
This is something I wind up looking for repeatedly, even though I wrote myself a nice little function a while ago. So, I figured others might benefit from having it and maybe I'll even find it here, myself. hahaha
It's pretty simple to paste into your script and use. Just pass it a folder object.
I think it requires PowerShell 3 just because of the -directory flag on the Get-ChildItem command, but I'm sure it can be easily adapted, if need be.
function Get-TreeSize ($folder = $null)
{
#Function to get recursive folder size
$result = #()
$folderResult = "" | Select-Object FolderPath, FolderName, SizeKB, SizeMB, SizeGB, OverThreshold
$contents = Get-ChildItem $folder.FullName -recurse -force -erroraction SilentlyContinue -Include * | Where-Object {$_.psiscontainer -eq $false} | Measure-Object -Property length -sum | Select-Object sum
$sizeKB = [math]::Round($contents.sum / 1000,3) #.ToString("#.##")
$sizeMB = [math]::Round($contents.sum / 1000000,3) #.ToString("#.##")
$sizeGB = [math]::Round($contents.sum / 1000000000,3) #.ToString("#.###")
$folderResult.FolderPath = $folder.FullName
$folderResult.FolderName = $folder.BaseName
$folderResult.SizeKB = $sizeKB
$folderresult.SizeMB = $sizeMB
$folderresult.SizeGB = $sizeGB
$result += $folderResult
return $result
}
#Use the function like this for a single directory
$topDir = get-item "C:\test"
Get-TreeSize ($topDir)
#Use the function like this for all top level folders within a direcotry
#$topDir = gci -directory "\\server\share\folder"
$topDir = Get-ChildItem -directory "C:\test"
foreach ($folderPath in $topDir) {Get-TreeSize $folderPath}
My proposal:
$dir="C:\temp\"
get-childitem $dir -file -Rec | group Directory | where Name -eq $dir | select Name, #{N='Size';E={(($_.Group.Length | measure -Sum).Sum / 1MB)}}
from sysinternals.com with du.exe or du64.exe -l 1 .
or 2 levels down:
**du -l 2 c:**
Much shorter than Linux though ;)
At the answer from #squicc if you amend this line: $topDir = Get-ChildItem -directory "C:\test" with -force then you will be able to see the hidden directories also. Without this, the size will be different when you run the solution from inside or outside the folder.
I used the great answer of #kohlbrr and improved it a bit. I also turned it into a function you can put in your $PROFILE. This outputs three properties instead of just text: Name, Size (which is a string output of the size converted to MB), and Value which is the raw size value you can use with | sort value
function Get-DirectorySize([string] $rootFolder) {
$colItems = Get-ChildItem $rootFolder | Where-Object {$_.PSIsContainer -eq $true} | Sort-Object
foreach ($i in $colItems) {
$subFolderItems = Get-ChildItem $i.FullName -recurse -force | Where-Object {$_.PSIsContainer -eq $false} | Measure-Object -property Length -sum | Select-Object Sum
[PSCustomObject]#{ Name=$i.Fullname; Size="{0:N2}" -f ($subFolderItems.sum / 1MB) + " MB"; Value=$subFolderItems.sum }
}
}
The following script provides file sizes from a directory(not going deep) and sizes in bytes.(give your path in $($args[0]) in both the scripts)
Get-ChildItem -Path "$($args[0])" -Recurse -Depth 0 -file| select Length,LastWriteTime,FullName | Export-Csv .\FileAndFolderSizes.csv -NoTypeInformation
The following script provides the folder sizes(depth 0 ) in bytes within the given directory.
$array= #()
Get-ChildItem -Path "$($args[0])" -Recurse -Depth 0 | Where-Object { $_.PSIsContainer } |
ForEach-Object {
$obj = New-Object PSObject
$Size = [Math]::Round((Get-ChildItem -Recurse $_.FullName | Measure-Object Length -Sum -ErrorAction SilentlyContinue).Sum, 2)
$obj |Add-Member -MemberType NoteProperty -Name "FullName" $_.FullName
$obj |Add-Member -MemberType NoteProperty -Name "LastWriteTime" $_.LastWriteTime
$obj |Add-Member -MemberType NoteProperty -Name "Length" $Size
$array +=$obj
}
$array | select Length,LastWriteTime,FullName | Export-Csv .\FileAndFolderSizes.csv -NoTypeInformation -Append
Output is as follows
"Length","LastWriteTime","FullName"
"593408","2/17/2022 10:51:01 PM","C:\a_appli\Partners_Ref\Client64_Rws2\compresslayer.dll"
"286720","2/9/2021 11:52:18 PM","C:\a_appli\Partners_Ref\Client64_Rws2\fdsrtd.dll"
"589312","6/19/2019 10:18:41 PM","C:\a_appli\Partners_Ref\Client64_Rws2\FdswCli.dll"
"13658276","3/18/2022 9:52:16 AM","C:\a_appli\Partners_Ref\Client64_Rws2\PartnersTemplateBuilder"
Interesting how powerful yet how helpless PS can be in the same time, coming from a Nix learning PS. after install crgwin/gitbash, you can do any combination in one commands:
size of current folder:
du -sk .
size of all files and folders under current directory
du -sk *
size of all subfolders (including current folders)
find ./ -type d -exec du -sk {} \;
I need to copy files to a folder until they exceed a specified size. I've written the following script but it fails with the following error:
Cannot compare "Microsoft.PowerShell.Commands.GenericMeasureInfo" because it is not IComparable.
At C:\33.ps1:8 char:1
+ "{0:N2}" -f ($colItems.sum / 1024MB)
$files = Get-ChildItem C:\source -Recurse | % { $_.FullName }
foreach($file in $files) {
do {
Copy-Item $file -Recurse D:\target
$colItems = (Get-ChildItem d:\target -recurse | `
Measure-Object -property length -sum)
"{0:N2}" -f ($colItems.sum / 1024MB)
}
while ($colItems -le 10)
}
What am I doing wrong?
The while condition will be verified after the first do loop. Since you already enumerate through the files, your script will copy all files.
You can omit the do-while loop and break the foreach if the limit is reached:
$files=Get-ChildItem C:\source -Recurse | % { $_.FullName }
$sum = 0
$sizeLimitInGB = 10
foreach($file in $files)
{
$colItems = (Get-ChildItem d:\target -recurse | Measure-Object -property length -sum)
if (($colItems.sum / 1GB) -gt $sizeLimitInGB)
{
break; # Limit reached.
}
Copy-Item $file -Recurse D:\target
}
I just wanted to build a small script which displays all files inside a folder (recursively) which are bigger than x MB. Somehow it shows me all files in that folder.
my script is here, can someone find the mistake ?
Param(
[string]$targetfolder
[string]$sizeinmb
)
function getfilesbigger
{
$colItems = (get-childitem "$targetfolder" -recurse | where {$_.length -gt $sizeinmbMB } | tee-object -variable allfiles | measure-object -property length -sum)
$allfiles | foreach-object {write-host $_.FullName ("{0:N2}" -f ($_.Length / 1MB)) "MB" -ForegroundColor "green" }
write-host "Collected all files bigger than $sizeinmb MB from folder $targetfolder " -foregroundcolor "darkgreen"
"Number of files: "+ $colItems.count + [Environment]::NewLine + "Size of all files "+"{0:N2}" -f ($colItems.sum / 1MB) + " MB"
}
getfilesbigger
where {$_.length -gt $sizeinmbMB}
$sizeinmbMB is $null - it hasn't been set. I think you're trying to pass 1 into the function and then append MB to the end of it, but string concatenation doesn't work this way.
Pass the actual size into the function (don't make this a "script", make it a reusable function that you can put somewhere for future use, like your own module), as an integer (if you use 1MB, it will be expanded automatically), when you call it.
function Get-FilesBigger {
[cmdletbinding()]
Param(
[ValidateScript({test-path -path $_ -pathtype container})]
[string]$Path,
[int]$MinFileSize
)
$colItems = get-childitem -path $Path -recurse | where-object {$_.length -gt $MinFileSize } | tee-object -variable allfiles | measure-object -property length -sum;
$allfiles | foreach-object {write-Verbose $($_.FullName + ("{0:N2}" -f ($_.Length / 1MB)) + "MB") };
"Collected all files bigger than " + $MinFileSize/1MB + "MB from folder $Path ";
"Number of files: "+ $colItems.count + [Environment]::NewLine + "Size of all files "+"{0:N2}" -f ($colItems.sum / 1MB) + " MB" ;
}
Get-FilesBigger -Path YOURPATH -MinFileSize 1MB -Verbose;
I believe you forgot to multiply $sizeinMB by 1MB before you did the file length comparison.
Your $sizeinmbMB should be $sizeinmb*1MB
i am very very new and i tried out a lot but i can't find a way how to add another property or something to my existing script.
i am searching for subfolder sizes and now i want to prevent the script from showing me empty folders by adding something like
| where-object size -gt 1KB OR something similar to it
i tried to put the pipeline behind others and i also tried to use an -and operator but i had no success. That's why i am asking you now :)
Thats my Script so far.
$startFolder = "C:\data1"
$colItems = (Get-ChildItem $startFolder | Measure-Object -property length -sum )
"$startFolder -- " + "{0:N2}" -f ($colItems.sum / 1MB) + " MB"
$colItems = (Get-ChildItem $startFolder -recurse | Where-Object {$_.PSIsContainer -eq $True} )
foreach ($i in $colItems)
{
$subFolderItems = (Get-ChildItem $i.FullName | Measure-Object -property length -sum -ea SilentlyContinue )
$i.FullName + " -- " + "{0:N2}" -f ($subFolderItems.sum / 1MB) + " MB"
}
if($subFolderItems.Sum -gt 0)
{
$i.FullName + " -- + {0:N2} MB" -f ($subFolderItems.sum/1MB)
}
Im looking to query the my documents folder for size, but also list the subfolders for size and export to a directory. I found some of this online and am trying to tweak to my needs but having issues with the export part, any help is GREATLY appreciated! :
$startFolder = "C:\Users"
$colItems = (Get-ChildItem $startFolder | Measure-Object -property length -sum)
"$startFolder -- " + "{0:N2}" -f ($colItems.sum / 1MB) + " MB"
add-content \\server\logs$\DirSize\log.log "$(gc env:computername)"
$colItems = (Get-ChildItem $startFolder -recurse | Where-Object {$_.PSIsContainer -eq $True} | Sort-Object)
foreach ($i in $colItems){
{
$subFolderItems = (Get-ChildItem $i.FullName | Measure-Object -property length -sum)
$i.FullName + " -- " + "{0:N2}" -f ($subFolderItems.sum / 1MB) + " MB" | add-content \\server\logs$\DirSize\log.log}}
Right now it is opening all folders under the C:\User\"User", can I limit to just one subdirectory under C:\Users\"User"? Thanks again!
Give this go:
$log = "C:\logfile.log"
$startFolder = "C:\Users"
$colItems = Get-ChildItem $startFolder | Where-Object {$_.PSIsContainer -eq $True} | Sort-Object
foreach ($i in $colItems){
$itemSum = Get-ChildItem ("$startFolder\" + $i.Name) -recurse | Measure-Object -property length -sum
"$startFolder\$i -- " + "{0:N2}" -f ($itemSum.sum / 1MB) + " MB" >> $log
}
This will output all the folders sizes within the given $startFolder and output the result to a log file ($log) that will look like this:
Start file: 'C:\test'
C:\test\config -- 0.00 MB
C:\test\docs -- 0.38 MB
C:\test\files -- 0.03 MB
C:\test\Help -- 7.28 MB
C:\test\inbox -- 0.00 MB
C:\test\install -- 0.00 MB
C:\test\jobs -- 0.00 MB
Stepping down 2 levels:
$log = "C:\logfile.log"
$startFolder = "C:\Users"
$colItems = Get-ChildItem $startFolder | Where-Object {$_.PSIsContainer -eq $True} | Sort-Object
foreach ($i in $colItems){
$itemSum = Get-ChildItem ("$startFolder\" + $i.Name) -recurse | Measure-Object -property length -sum
"$startFolder\$i -- " + "{0:N2}" -f ($itemSum.sum / 1MB) + " MB" >> $log
$colItems2 = Get-ChildItem ("$startFolder\" + $i.Name) | Where-Object {$_.PSIsContainer -eq $True} | Sort-Object
foreach ($j in $colItems2){
If($j -ne $null){
$itemSum2 = Get-ChildItem ("$startFolder\" + $i.Name +"\"+ $j.Name) -recurse | Measure-Object -property length -sum
"-->$startFolder\$i\$j -- " + "{0:N2}" -f ($itemSum2.sum / 1MB) + " MB" >> $log
}
}
}
This will recurse all subdirectories of the tree and get their respective sizes:
Param($Path = $(throw "Missing directory")
,$CSVFile = $(throw "Missing logfile")
)
Function GerDirSize($PathDir)
{
#Gets subdirectories
$dirs = Get-ChildItem $PathDir | Where-Object {$_.PsIsContainer}
#Check if the list is empty
if($dirs -ne $null)
{
foreach($dir in $dirs)
{
#Gets size of current directory
$itemSum = Get-ChildItem $dir.FullName -recurse | Where-Object {!$_.PsIsContainer} | Measure-Object -Property length -Sum
$itemSum = "{0:N2}" -F ($itemSum.sum / 1MB)
$result = $dir.FullName + ";" + $itemSum
Add-Content $CSVFile -Value $result
#Gets size of subdirectories
GerDirSize($dir.FullName)
}
}
}
GerDirSize $Path
Name it GetDirSize.ps1 and use it as follows:
GetDirSize.ps1 "c:\temp" "c:\temp\logfile.log"
The result will be:
C:\temp\directory1;10.34
C:\temp\directory1\subdirectory1;2.07
C:\temp\directory1\subdirectory1\subsub1;0.00
C:\temp\directory1\subdirectory2;6.21
C:\temp\directory1\subdirectory3;0.00
C:\temp\directory2;4.14
C:\temp\directory3;10.34
C:\temp\directory3\subdirectory1;4.14
C:\temp\directory3\subdirectory1\subdirectory1;2.07
C:\temp\directory4;0.00