Count total files and folders of a drive powershell - windows

Ctrl + A and right click properties in C:\ shows the number and size of all the files and folders of the drive.
How should I do it in powershell?? I need the exact and count so that the output of the script shows the same result.
I tried Get-ChildItem "C:\" -recurse | Measure-Object -property length -sum
Output is
Count : 102809
Average :
Sum : 25145552806
Property : length
But thats not the correct number
thanks in advance

You should use the force parameter of get-childitem.
from the doc :
-Force
Allows the cmdlet to get items that cannot otherwise not be accessed by the user, such as hidden or system files. Implementation varies among providers. For more information, see about_Providers (http://go.microsoft.com/fwlink/?LinkID=113250). Even when using the Force parameter, the cmdlet cannot override security restrictions.
Of course you have to run this from an elevated powershell console.
After trying my self I hit the same error.
I'd like to suggest another way to do it using WMI :
$drive=gwmi win32_logicaldisk -Filter "deviceid='c:'"
$usedspace = $drive.Size -$drive.FreeSpace

Related

Windows PowerShell - Input file name, output file path

I've just started using PowerShell and I have a task where I need to be able to have the file path displayed on screen when I enter the file name.
Is there a script that allows me to do the below ? :
Ex 1: I enter "test.txt" and I get "C:\Program Files...."
Ex 2: I enter a file name "My Documents" and I also get its path.
I have searched online on how to do this but I didn't quite find what I was looking for and all the queries/answers were too complicated for me to understand.
Can anyone help me out, please?
Thanks in advance!
Here is a starter sample for you.
This example search only within the confine of the paths present is the Path system environment variable. It also only looks for files and do not recurse through these path.
So anything you could access directly from the command line should be available to you through it.
Now, if you want to search the whole drive, you could replace the $DefaultPaths assignment with Get-ChildItem -Path 'C:' -Recurse but doing that each time won't be super efficient.
You could do it and it will work... but it will be slow.
To search on the whole drive or whole filesystem, there are alternative methods that might work better. Some examples of what might entice:
Using a database which you have to buld & maintain to index all the files so that when you search, results are instantaneous and / or very fast
Parsing the MFT table (if using Windows / NTFS filesystem only) instead of using Get-ChildItem (This is not somehting natively doable through a simple cmdlet though) .
Relying on a third party software and interface with (For example, Void Tools Everything search engine already parse MFT and build its own database, allowing users to search instantly through a Windows NTFS filesystem. It also have its own SDK you can plug in through Powershell and retrieve what you seek instantly. The caveats is that you need the software installed first for that solution to work.)
Example: Searching through all paths defined in the Path variable
# What you are looking for. Accept wildcards characters (*)
$Filter = 'notepad.exe'
# Get the System Environment Path variable in an array
$DefaultPaths = $env:Path -split ';'
$Paths =
Foreach ($P in $DefaultPaths) {
# Search for files matching the specified filter. Ignore errors (often if the path do not exist but is sin the Path)
$MatchingFiles = Get-ChildItem -Path $P -Filter $Filter -File -ErrorAction SilentlyContinue
if ($MatchingFiles.count -gt 0) {
$MatchingFiles.Directory.FullName
}
}
$Paths | out-string | Write-Host -ForegroundColor Cyan
Output for Notepad.exe search using this method.
C:\Windows\system32
C:\Windows

Is there any way to find 'metadata' on folders using powershell

So I want to know if any of the folders in a directory have any subfolders or files in them, I tried just looking at the directory in PowerShell but it gave me only mode, last write time, and name. Is there any way of adding to this list to include metadata of the folder like size or number of subfiles/folders all I want to know is if they are empty or not so there may be a simpler way I'm missing.
Thanks for any help you can give!
I see the question is tagged 'windows', so on Windows you could also use a COM object.
$fso = New-Object -ComObject Scripting.FileSystemObject
$folder = $fso.GetFolder($pathToFolder)
$folder will be an object with a bunch of interesting metadata on it, including SubFolders and Files. One of the interesting ones is Size. If Size is zero, there are no files in that directory, or in any nested subdirectories either.
If you just want to know if there are folders/subfolders and/or files then this will work:
$folder="C:\Test"
Get-ChildItem $folder -Recurse | Measure-Object
Output (in my case)
Count : 2
Average :
Sum :
Maximum :
Minimum :
Property :
If you want to see more properties then this might work for you:
Get-ChildItem -Path $folder -Recurse | Format-List *
alternatively you can also select the first x, last x, or even skip items:
Get-ChildItem -Path $folder -Recurse |Select-Object -First 2| Format-List *
*-Recurse will check all folders below

Get-ChildItem with wild chars in path without "Where"

I want to use wild characters in path passed to Get-ChildItem. So in example I want to use C:\root\*\container as a path parameter. But this searches only in 1 level below. If I would write C:\root\*\*\container then it would search 2 levels below only.
I try to do something like Get-ChildItem -Path "C:\root\*\container\vc$number" "*test*.exe" -Recurse
and copy results into certain directory. If I search recursively in C:\root I find too many files. If I use path given in an example then I search only 1 level below, not recursively in all directories (that can be even 5 levels deep). I know I can use
Get-ChildItem -Path "C:\root\" "*test*.exe" -Recurse | Where { %_.FullName -like "container\vc$number" }
but I was wondering if I can skip using Whereand use wild chars in path. Reason for that is I read paths from external file and some paths contain wild chars (as example above) and some don't. So I hope I don't have to write function that processes path and uses Get-ChildItem with / without Where
So in example I have
C:\root\container\*test*.exe, C:\root\a\container\*test*.exe, C:\root\b\container\*test*.exe, C:\root\c\x\y\container\*test*.exe, C:\root\c\x\y\z\g\container\*test*.exe
and so on. And with C:\root\*\container I want to find all of them
Get-Childitem has a parameter Filter which you can use to filter the results you want. In your case (as i understood) you want to get files in all the directories named "container".
First you have to get the path to these directories, then get the files inside as follows:
Get-ChildItem "C:\root" -filter "*container*" -recurse | Get-ChildItem
Output
C:\root\a\container\new.exe
C:\root\b\container\sample.exe
C:\root\c\x\y\z\g\container\anything.exe
I used .Fullname at the end to get them displayed as above

Powershell renaming special directories recursively

I got this folder structure
C:\Users\myUser\Desktop
including folders called
BL-100
BL-105
BL-108
and so on...
most BL-folders storing a file.xml, but not all.
So on Desktop are much folders starting with BL- and the most, but not all, storing a file.xml.
Now I want to search all folders which are starting with BL- and store a file.xml and rename those folders to RG-100, RG-105, RG-108 and so on
At the moment I got this script:
foreach($Directory in Get-ChildItem -Path C:\Users\myUser\Desktop -Recurse | Where-Object{($_.Name.Substring(0,3) -eq 'BL-')}){
}
This does not work and is showing me error: Exception calling "Substring" with "2" argument(s): "Index and length must refer to a location within the string. Parameter name: length"
Anyone can help please?
The error you're seeing is because SubString fails for some reason. The most likely reason would be if the string is not long enough; e.g. if you had a folder with a 1 character long name. To see what I mean, try running: '1'.Substring(0,2).
To avoid this, instead you could use the like operator. e.g.
foreach($Directory in (
Get-ChildItem -LiteralPath 'C:\Users\myUser\Desktop' -Recurse `
| Where-Object{($_.Name -like 'BL-*')}
)){
#...
}
Just do it:
Get-ChildItem "C:\Users\myuser\Desktop" -directory -Filter "BL-*"

In PowerShell, how can I extract a file from HKEY_Users from all SIDs?

I am writing a PowerShell module to look for data that each user who has logged onto the computer at some point might have in their directory in HKEY_USERS. My initial thought was to mount HKEY_USERS, find a way to store each user's SID in a string variable, and then loop through all folders like so:
dir HKU\<STRING VARIABLE HOLDING SID>\Software\MyApp\Mydesireddata
Is there a way I can avoid having to loop through SIDs (because I won't know them ahead of time), and extract that file info from each SID on the system while remembering which SID it came from?
EDIT: Here is an example of the key I'm trying to extract from each user's SID using regedit (vncviewer's EulaAccepted)
Use Get-ChildItem to retrieve each user-specific subkey:
$UserHives = Get-ChildItem Registry::HKEY_USERS\ |Where-Object {$_.Name -match '^HKEY_USERS\\S-1-5-21-[\d\-]+$'}
Then loop over each entry and retrieve the desired registry value:
foreach($Hive in $UserHives)
{
# Construct path from base key
$Path = Join-Path $Hive.PSPath "SOFTWARE\MyApp\DataKey"
# Attempt to retrieve Item property
$Item = Get-ItemProperty -Path $Path -Name ValueName -ErrorAction SilentlyContinue
# Check if item property was there or not
if($Item)
{
$Item.ValueName
}
else
{
# doesn't exist
}
}
I tackled this issue a slightly different way; preferring to make use of a conspicuously placed wildcard.
Get-ItemProperty -Path Registry::HKEY_USERS\*\SOFTWARE\TestVNC\viewer\ -Name EulaAccepted |
Select-Object -Property #{n="SID";e={$_.PSPath.Split('::')[-1].Split('\')[1]}},EulaAccepted
The wildcard will automatically check all available paths and return what you need as well as the SID from the parent path.
As for the username (which is probably more useful than a SID), you didn't specifically ask for it, but I added it in for grins; this should cover local and domain accounts.
mind the line breaks
Get-ItemProperty -Path Registry::HKEY_USERS\*\SOFTWARE\TestVNC\viewer\ -Name EulaAccepted |
Select-Object -Property #{n="SID";e={$_.PSPath.Split('::')[-1].Split('\')[1]}},EulaAccepted |
Select-Object -Property #{n="User";e={[System.Security.Principal.SecurityIdentifier]::new($_.SID).`
Translate([System.Security.Principal.NTAccount]).Value}},SID,EulaAccepted
Getting the username is just ugly; there's likely a cleaner way to get it, but that's what I have in my head. The double-select really makes my skin crawl - there's something unpleasant about it. I could just do a one shot thing, but then it gets so unwieldly you don't even know what you're doing by looking at it.
I've included a screenshot of the registry below, and a screenshot of the screen output from running the few lines.

Resources