PowerShell to find folder / file size - powershell

I am trying to write a script using powershell to get folder / file size as mentioned below
$StartFolder = "D:\"
$Output = "C:\Temp\test-d.csv"
Add-Content -Value "Folder Path|Size" -Path $Output
$colItems = (Get-ChildItem $startFolder -Recurse | Measure-Object -Property Length -Sum)
"$StartFolder -- " + "{0:N2}" -f ($colItems.Sum / 1MB) + " MB" # | Out-File $Output
$colItems = (Get-ChildItem $startFolder -Recurse | Where-Object {$_.PSIsContainer -eq $True} | Sort-Object)
foreach ($i in $colItems) {
$subFolderItems = (Get-ChildItem $i.FullName -Recurse | Measure-Object -Property Length -Sum)
$i.FullName + "|" + "{0:N2}" -f ($subFolderItems.Sum / 1MB) + " MB" | Out-File $Output -Append
}
I am getting error as mentioned below:
Measure-Object : The property "Length" cannot be found in the input for any
objects.
At line:12 char:65
+ $subFolderItems = (Get-ChildItem $i.FullName -Recurse | Measure-Object - ...
+
+ CategoryInfo : InvalidArgument: (:) [Measure-Object], PSArgumentException
+ FullyQualifiedErrorId : GenericMeasurePropertyNotFound,Microsoft.PowerShell.Commands.MeasureObjectCommand
Measure-Object : The property "Length" cannot be found in the input for any
objects.
At line:12 char:65
+ $subFolderItems = (Get-ChildItem $i.FullName -Recurse | Measure-Object - ...
+
+ CategoryInfo : InvalidArgument: (:) [Measure-Object], PSArgumentException
+ FullyQualifiedErrorId : GenericMeasurePropertyNotFound,Microsoft.PowerShell.Commands.MeasureObjectCommand
Also, when I target C: drive I am getting "access denied" on some system files:
Get-ChildItem : Access to the path 'C:\Windows\System32\LogFiles\WMI\RtBackup'
is denied.
At line:12 char:28
+ $subFolderItems = (Get-ChildItem $i.FullName -Recurse | Measure-Object - ...
+
+ CategoryInfo : PermissionDenied: (C:\Windows\Syst...es\WMI\RtBackup:String) [Get-ChildItem], UnauthorizedAccessException
+ FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand

DirectoryInfo objects don't have a property Length, so you need to restrict your size calculation to files.
$colItems = Get-ChildItem $startFolder -Recurse -Force |
Where-Object { -not $_.PSIsContainer } |
Measure-Object -Property Length -Sum
It might be easier to use a Scripting.FileSystemObject COM object, because that will allow you to get directory objects with the size of their content. And you may want to use Export-Csv for exporting your data to a CSV. Use calculated properties for building the required objects.
$fso = New-Object -COM 'Scripting.FileSystemObject'
$folders = #($StartFolder)
$folders += Get-ChildItem $StartFolder -Recurse -Force |
Where-Object { $_.PSIsContainer } |
Select-Object -Expand FullName
$folders |
Select-Object #{n='Path';e={$_}}, #{n='Size';e={$fso.GetFolder($_).Size}} |
Export-Csv $Output -Delimiter '|' -NoType

Related

PowerShell ISE .jpg and .png summary size (Windows and its subdirectories)

I am looking for a solution to this problem: Find the summary size of .jpg and .bmp files in Windows and its subdirectories.
I use the following commands:
Get-ChildItem -Force -Depth 2 -Path C:\Windows\ | Where-Object -Property Extension -Match "\.(bmp|jpg)$" | Measure-Object -Property Length -Sum | Select-Object -Property Sum
How do I count the actual summary size without getting an access error:
The output is:
Get-ChildItem : Access to the path 'C:\Windows\CSC\v2.0.6' is denied.
At line:1 char:1
+ Get-ChildItem -Force -Depth 2 -Path C:\Windows\ | Where-Object -Prope ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (C:\Windows\CSC\v2.0.6:String) [Get-ChildItem], UnauthorizedAccessException
+ FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand
Sum
---
35241685
Thank You.
To get all *.bmp and *.jpg files and to sum their length you can do:
$measure = Get-ChildItem -path $env:SystemRoot* -Include #('*.bmp','*.jpg') -ErrorAction:SilentlyContinue -Recurse | Measure-Object -Property length -sum
But this is quite slow. By using the parameter "-Filter" this runs much much faster, but you have to do 2 calls as the parameter "-Filter" only accepts a string and not a array:
#Get files
$files = #(
get-childitem -path $env:SystemRoot -Filter '*.jpg' -Recurse -ErrorAction:SilentlyContinue
get-childitem -path $env:SystemRoot -Filter '*.bmp' -Recurse -ErrorAction:SilentlyContinue
)
#Get count and sum
$measure = $files | Measure-Object -Property length -sum
Finally to avoid the "path too long" issue:
#Get files
$files = #(
get-childitem -pspath "\\?\C:\Windows" -Filter '*.jpg' -Recurse -ErrorAction:SilentlyContinue
get-childitem -pspath "\\?\C:\Windows" -Filter '*.bmp' -Recurse -ErrorAction:SilentlyContinue
)
#Get count and sum
$measure = $files | Measure-Object -Property length -sum
See: https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry

Measure-Object : The property "length" cannot be found in the input for any objects

I'm creating a menu and one of the options is to report on folder size for a specified folder and display it back to the user. After I put in the folder name
cls
$Path = Read-Host -Prompt 'Please enter the folder name: '
$FolderItems = (Get-ChildItem $Path -recurse | Measure-Object -property length -sum)
$FolderSize = "{0:N2}" -f ($FolderItems.sum / 1MB) + " MB"
I get the following error:
Measure-Object : The property "length" cannot be found in the input for any objects.
At C:\Users\Erik\Desktop\powershell script.ps1:53 char:48
+ ... (Get-ChildItem $Path -recurse | Measure-Object -property length -sum)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Measure-Object], PSArgumentException
+ FullyQualifiedErrorId : GenericMeasurePropertyNotFound,Microsoft.PowerShell.Commands.
MeasureObjectCommand
There are no files in the folders, so you only get DirectoryInfo-objects which doesn't have a length-property. You can avoid this by filtering for files-only using:
(Get-ChildItem $Path -Recurse | Where-Object { -not $_.PSIsContainer } | Measure-Object -property length -sum)
Or for PS 3.0+
(Get-ChildItem $Path -Recurse -File | Measure-Object -property length -sum)

get-childitem : Cannot find path ' ' because it does not exist

I am trying to make a script that can report on a folder size for a specified folder.
I keep getting this error after I put in the folder name and I know the folder exists.
Also if I don't get this error then I always get 0 MB.
get-childitem : Cannot find path 'C:\WINDOWS\system32\downloads' because it does not exist.
At C:\Users\Erik\Desktop\powershell script.ps1:58 char:12
+ $folders = get-childitem $startfolder | where{$_.PSiscontainer -eq "T ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\WINDOWS\system32\downloads:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound, Microsoft.PowerShell.Commands.GetChildItemCommand
Code
$startfolder = Read-Host -Prompt 'Please enter the folder name:'
#check that input is not empty
if([string]::IsNullOrEmpty($startfolder)) {
Write-Host "folder name is NULL or EMPTY"
} else {
$folders = get-childitem $startfolder | where {$_.PSiscontainer -eq "True"}
"folder Name`tfolder Size (MB)"
foreach ($fol in $Folders) {
$colItems = (Get-ChildItem $fol.fullname -recurse | Measure-Object -property length -sum)
$size = "{0:N2}" -f ($colItems.sum / 1MB)
"$($fol.name)`t$size"
}
}
so.. My power-shell is a bit terrible but I've got this working for me:
$startfolder = Read-Host -Prompt 'Please enter the folder name:'
#check that input is not empty
if([string]::IsNullOrEmpty($startfolder)) {
Write-Host "folder name is NULL or EMPTY"
}
else {
$subFolderItems = Get-ChildItem $startfolder.FullName -recurse -force | Where-Object {$_.PSIsContainer -eq $false} | Measure-Object -property Length -sum | Select-Object Sum
$startfolder + " -- " + "{0:N2}" -f ($subFolderItems.sum / 1MB) + " MB"
}
the output is like:
test -- 2.65 MB

How to declare a snippet containing variables as a variable to avoid code duplication using PowerShell?

The snippet (Get-Content $_.FullName | Select-Object -First 1) is called three times. The aim is to declare it as a variable to avoid code duplication.
Get-ChildItem "$env:ChocolateyInstall\lib\eclipse.*" -Recurse -Filter "eclipseInstall.zip.txt" |
ForEach-Object{ if (((Get-Content $_.FullName | Select-Object -First 1) -match "eclipse") -and (Test-Path -Path (Get-Content $_.FullName | Select-Object -First 1))){Remove-Item -Recurse -Force (Get-Content $_.FullName | Select-Object -First 1)}}
Attempt
$a = (Get-Content $_.FullName | Select-Object -First 1)
Get-ChildItem "$env:ChocolateyInstall\lib\eclipse.*" -Recurse -Filter "eclipseInstall.zip.txt" |
ForEach-Object{ if (($a -match "eclipse") -and (Test-Path -Path (Get-Content $_.FullName | Select-Object -First 1))){Write-Host "hello"}}
Result
PS C:\Windows\system32> . "C:\temp\powershelltest\test.ps1"
Get-Content : Cannot bind argument to parameter 'Path' because it is null.
At C:\temp\powershelltest\test.ps1:1 char:19
+ $a = (Get-Content $_.FullName | Select-Object -First 1)
+ ~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-Content], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.GetContentC
ommand
You can assign a snippet of code to a variable like this:
$a = { Get-Content $_.FullName | Select-Object -First 1 }
Then execute the snippet at any time with & $a (you would need to pipe an object to it). I'm not sure this is necessary in your example though.

Query Folder tree for Size and export to a log on a server

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