powershell and windows explorer (properties) have different count results - powershell

I'm recursively counting total number of objects (files, folders, etc) to check folders vs their Amazon S3 backups.
When I use windows explorer on a folder (right click --> properties), I get a smaller number of total objects than what the following powershell code generates. Why?
Amazon S3 matches the count from Windows Explorer 100% of the time. Why is powershell giving a higher total number, and what is the likely difference (system files, hidden files, etc)? The total number of objects in these folders is routinely 77,000+.
folder_name; Get-ChildItem -Recurse | Measure-Object | %{$_.count}

I was unable to replicate.
When in file explorer, right-click the folder in question -> properties
Under the General tab, there's a section called Contains.
This lists both the Files and Folders as separate numbers.
In my example I have 19,267 Files, 1,163 Folders which is a total of 20,430 objects
When I run
Get-ChildItem -Path C:\folder -Recurse | measure | % Count
it returns 20430
When I run
Get-ChildItem -Path C:\folder -Recurse | ?{$_.PSiscontainer -eq $false} | measure | % count
it returns 19267
When I run
Get-ChildItem -Path C:\folder -Recurse | ?{$_.PSiscontainer -eq $true} | measure | % count
it returns 1163
Are you certain that you're counting both the files and folders when manually viewing the properties?

The discrepancy comes from Windows Explorer counting files, and separately, folders. Powershell (version 2.0 Build 6.1) is counting everything together. It seems -File and -Directory don't work in PowerShell V2.0.
I really want to be able to get a list as a .cvs or .txt output of just the number of files (recursively) from a large number of folders. Going through windows explorer is one by one, and I don't get this as an output that I can copy/paste.

To count the number of files and folders in separate variables, you can do
# create two variables for the count
[int64]$totalFolders, [int64]$totalFiles = 0
# loop over the folders in the path
Get-ChildItem -Path 'ThePath' -Recurse -Force -ErrorAction SilentlyContinue | ForEach-Object {
if ($_.PSIsContainer) { $totalFolders++ } else { $totalFiles++ }
}
# output the results
"Folders: $totalFolders`r`nFiles: $totalFiles"
The -Force switch makes sure also hidden and system files are counted.
A probably faster alternative is to use robocopy:
$roboCount = robocopy 'ThePath' 'NoDestination' /L /E /BYTES
$totalFolders = #($roboCount -match 'New Dir').Count - 1 # the rootfolder is also counted
$totalFiles = #($roboCount -match 'New File').Count
# output the results
"Folders: $totalFolders`r`nFiles: $totalFiles"

Related

Using get-childitem -Exclude to avoid recycle bin, windows, program files

I am trying to exclude the "recycle bin", "Windows", and "Program Files" folders in my recursive call to Get-ChildItem.
I figured it would just be -Exclude '$Recycle.Bin', 'Windows', 'Program Files' or -Exclude 'C:\$Recycle.Bin', 'C:\Windows', 'C:\Program Files', but neither of these give me the wanted result. Any ideas? Thanks
Exclude does not filter out child objects found within excluded directories when you use the Recurse option. The answer over here contains a good explanation about this:
How to exclude files and folders from Get-ChildItem in PowerShell?
You can accomplish what you want by stringing together multiple calls as the other answer suggested. Here is a sample one-liner PowerShell command that lists all files greater than 1GB in size, excluding the directories you listed:
Get-ChildItem C:\ -Directory | Where-Object Name -NotIn #('Windows','Program Files','$Recycle.Bin') | % { Get-ChildItem -File $_.FullName -Recurse} | Where-Object {($_.Length /1GB) -gt 1} | Sort -Descending -Property Length | Format-Table Length, FullName -AutoSize -Wrap
Here is a breakdown of how this one-liner works:
The first Get-ChildItem returns all Top Level directories under your C:\ drive.
These directories are then piped (|) into the Where-Object cmdlet, where we use the -NotIn parameter to specify an array of directory names to exclude.
This filtered set of Top Level directories is then passed into the ForEach-Object cmdlet denoted here with the % alias.
Each of the directories is then passed in one-by-one into another Get-ChildItem cmdlet which does the recursive search you desire. (Note that I used the -File filter to only return files)
That should cover what you asked for in your original question. The second Where-Object cmdlet filters files over 1GB in size, then those get sorted by file size, and the result is printed out in table format. You probably want to replace these parts with whatever you were trying to do.
If you want to use different types of filters instead of the NotIn filter, take a look at all the other options availabe in the Where-Object doc.
You could use this syntax instead to achieve the same effect.
$Directories = Get-ChildItem c:\ -Directory | Where-Object Name -NotIn #('Windows','Program Files','$Recycle.Bin')
$Output = $Directories | % { Get-ChildItem $_.FullName -Recurse}

Count all files in folder and subfolder + folders that says 0 files

I'm trying to run a Powershell command or CMD command, that count all files in 1 folder and its subfolder. I got a script that count all files, but it does not find hidden files. The problem I found was in my network share there was a folder that said 0 files, but when I go into the folder there are a lot of files in there.
Is there a way to get those files into the count?
I have tried a few Powershell command and CMD commands.
Get-ChildItem -Recurse -File | Measure-Object | %{$_.Count}
I can only get it to count files Windows can see, if a folder says 0 files but there are files in there, it does not count it.
Use the force
PS> Get-ChildItem -Path c:\test | Measure-Object | Select-Object -ExpandProperty Count
16
PS> Get-ChildItem -Path c:\test -Force | Measure-Object | Select-Object -ExpandProperty Count
17
The -Force parameter on Get-ChildItem will force inclusion of hidden files

Powershell script to list large files on multiple servers

I have been trying to create/modify a Powershell script that allows me to automate finding all files across multiple servers larger than 1GB and excluding .ldf and mdf.
I have found a script, but it only looks into the current C Drive and although I've been trying to modify this, I have been unsuccessful.
I'm unsure how to modify this to fit finding multiple servers.
gci -r|sort -descending -property length | select -first 10 name, #{Name="Gigabytes";Expression={[Math]::round($_.length / 1GB, 2)}}
Please help.
Complete Script:
$size=1GB
$path="C:\"
$omit="*.mdf,*.ldf"
Get-ChildItem -Path $path -Exclude $omit -Recurse -OutBuffer 1000|
where {($_.Length -gt $size)}|Select Name, Directory, Length
Sample Output:
Name Directory Length
---- --------- ------
CAP2015-07-29 21-07-08-71.avi C:\ 1216624984
CAP2015-07-29 21-08-17-48.avi C:\Movies 1205696024
Explination of Script:
Variable for controlling search size. Can be KB, MB, GB
$size=1GB
Variable to set base path to search from
$path="C:\"
Variable to set list of excluded extensions
$omit="*.mdf,*.ldf"
Searches through all items from the $Path recursively and returns only files that are over the set size controlled by $size, and omits files listed in $omit.
Get-ChildItem -Path $path -Exclude $omit -Recurse -OutBuffer 1000|
where {($_.Length -gt $size)}|Select Name, Directory, Length
NOTE: The -OutBuffer parameter controls how many items are gathered before continuing. Managing this parameter correctly can greatly increase the speed with which a command completes. This is from a group of parameter called "CommonParameters". Knowing what these are, and how they work is invaluable.Microsoft Docs about_CommonParameters

Moving files/folders based on creation date and keeping folder structure

Windows 7 Pro environment.
I'm looking to create a batch or PowerShell script to move folders based on creation or last modified date.
The source folder is "D:\Video". The destination is "F:\DVRBackups\".
The requirement is that the folder structure be maintained, and that only folders older than a certain creation date are moved, whilst the others are left untouched.
The folder structure for the source folder looks like this:
D:\Video\Cam01\XXXX
D:\Video\Cam02\XXXX
D:\Video\Cam03\XXXX
..etc..
(XXX = hundreds of folders within the Cam01/02/03 folders spanning months)
The number of camera folders changes based on the computer DVR box i'm working on. Some locations have 5 cameras, some have as many as 35 (i.e., Cam01, Cam02, .., Cam35).
Folders from within the Cam01/02/03 folders need to be moved over to F:\DVRBackups, whilst maintaining the original folder structure.
i.e.
D:\Video\Cam01\0318 --> F:\DVRBackups\Video\Cam01\0318
D:\Video\Cam01\0319 --> F:\DVRBackups\Video\Cam01\0319
D:\Video\Cam02\0501 --> F:\DVRBackups\Video\Cam02\0501
..etc..
Can someone assist?
If it's just the folders within each CamXX folder that you need to check the Last modified time and them move. You can use the following in PowerShell.
$source = "D:\Video\"
$destination = "F:\DVRBackups\"
$date = Get-Date "25/03/2015 12:00"
dir $source | %{ dir $_.FullName | ?{ $_.LastWriteTime -gt $date } | Copy-Item -Destination $destination -Recurse -Force }
If you want to test what folders will be moved before hand use this command first.
dir $destination | %{ dir $_.FullName | ?{ $_.LastWriteTime -gt $date } | select LastWriteTime, FullName }
This will provide a list of the all folders that will have all there content moved.

PowerShell command to delete a directory containing large redundant folders

Is there a PowerShell command to delete a directory containing large redundant folders?
1-2 TB are in each folder. How would I write this? Doing it via Windows Explorer is too slow.
To remove folder you can use Remove-Item cmdlet
Remove-Item -Recurse -Force $pathToDelete
The command above will delete $pathToDelete with all its contents.
If you want to delete only items which meet certain conditions, e.g. files greater than 1 GB contained in the current directory, you can write something like:
Get-Childitem . -Recurse | Where-Object { $_.length -gt 1gb } | Foreach ($_) { Remove-Item $_.FullName }