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

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

Related

Use Powershell to delete ShellIconOverlayIdentifiers on Windows

I am currently very annoyed by Dropbox and Nextcloud, which both battle the ShellIconOverlayIdentifier list. A problem which many people seem to have, when you search the internet.
Now I want to combine my annoyance with my intent to learn powershell (7.2.0).
I started with the following script, which shall retrieve all keys. And later I want to use regex via -match to find the entries I want to delete. For now I work with both Remove-Item -WhatIf and Get-ItemProperty to test it.
Currently my problem is that I can create my list as intended. But when I feed the list into the remove command I get that the path cannot be found. What am I doing wrong?
Push-Location -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers
$list = Get-ChildItem -Path .
$filteredList = $list -match "DropboxExt10"
$filteredList
# Remove-Item -WhatIf -Recurse $filteredList
Get-ItemProperty $filteredList
Pop-Location
The error is Cannot find path 'Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\ DropboxExt10' because it does not exist. Apparantly it adds the path as relative path to the current location. Why doesn't it interpret as an absolute path? When I ommit the push-location part it trys to add the registry path to my current working directory in which the script lives. But this is wrong as well.
Thanks for your help in advance.
Use one of the following:
$filteredList | Remove-Item -WhatIf -Recurse
# Alternatively:
Remove-Item -LiteralPath $filteredList.PSPath -WhatIf -Recurse
The above commands ensure that the registry items (keys) are bound by their full, provider-qualified paths to Remove-Item's -LiteralPath parameter, via their .PSPath property; in the case of registry paths, the path's provider prefix is Microsoft.PowerShell.Core\Registry:: (or, if identifying the originating module isn't also required, Registry::, as used in your Push-Location call)
What appears to be happening is that when the items are stringified - which is what happens when you pass them as a whole, as an argument (e.g. Remove-Item $filteredlist, which is the same as Remove-Item -Path $filteredlist), they lack the provider prefix and are represented as registry-native paths.
And given that a full registry-native path such as HKEY_LOCAL_MACHINE\... neither starts with a drive specification nor with \ or /, it is interpreted as a relative path, resulting in the symptom you saw.

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

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-*"

Script to compare two different folder contents and rename them based on minimum similarity

Story:
I have multiple folders with 1000+ files in each that are named similar to each other but are slightly different but they relate to the same content.
For example, in one folder I have files named quite simply "Jobs to do.doc" and in another folder "Jobs to do (UK) (Europe).doc" etc.
This is on Windows 10, not Linux.
Question:
Is there a script to compare each folder's content and rename them based on minimum similarity? So the end result would be to remove all the jargon and have each file in each folder (multiple) the same as one another but STILL remain in the retrospective folder?
*Basically compare multiple folder content to one folders contents and rename them so each file in each folder is named the same?
Example:
D:/Folder1/Name_Of_File1.jpeg
D:/Folder2/Name_Of_File1 (Europe).jpeg
D:/Folder3/Name_of_File1_(Random).jpeg
D:/folder1/another_file.doc
D:/Folder2/another_file_(date_month_year).txt
D:/Folder3/another_file(UK).XML
I have used different file extensions in the above example in hope someone can write a script to ignore file extensions.
I hope this make sense. So either a script to remove the content in brackets and keep the files integrity or rename ALL files across all folders based on minimum similarity.
The problem is its 1000+ files in each folder so want to run it as an automated job.
Thanks in advance.
If the stuff you want to get rid of is always in brackets then you could write a regex like
(.*?)([\s|_|]*\(.*\))
Try something like this
$folder = Get-ChildItem 'C:\TestFolder'
$regex = '(.*?)([\s|_|]*\(.*\))'
foreach ($file in $folder){
if ($file.BaseName -match $regex){
Rename-Item -Path $file.FullName -NewName "$($matches[1])$($file.extension)" -Verbose #-WhatIf
}
}
Regarding consistency you could run a precheck using same regex
#change each filename if it matches regex and store only it's new basename
$folder1 = get-childitem 'D:\T1' | foreach {if ($_.BaseName -match $regex){$matches[1]}else{$_.BaseName}}
$folder2 = get-childitem 'D:\T2' | foreach {if ($_.BaseName -match $regex){$matches[1]}else{$_.BaseName}}
#compare basenames in two folders - if all are the same nothing will be returned
Compare-Object $folder1 $folder2
Maybe you could build with that idea.

What's the proper syntax to set a Powershell filter variable based on multiple values?

I have a PowerShell Script that processes files in a directory based on selection criteria. For one run, I need to act on all HTML files, so I'm using the following code.
$bkppath = "\\filepath"
$selectionFilter = "*.htm*"
$srcfiles = Get-ChildItem $bkpPath -filter $selectionFilter
ForEach($doc in $srcfiles) {
do-stuff
}
For another run, I need to act on anything that's not related to the HTML in the directory, so I want to EXCLUDE *.htm*, *.js, *.ico and *.xml. I've not been able to find the proper syntax for applying those multiple values to my selectionFilter variable.
I need something like this:
$selectionFilter = !("*.htm*" or ".js" or "*.xml" or "*.ico")
or
$srcfiles = Get-ChildItem $bkpPath -filter !("*.htm*" or ".js" or "*.xml" or "*.ico")
both of which give me a syntax error.
I've not been able to find anything on MSDN that covers how to handle multiple values like this. Can you please point me in the right direction?
While -exclude *.ico, *.js, *xml is to correct syntax for the exclusion, an important caveat is that the pathname to which the exclusion is applied MUST end with \* in order for this to work. -filter does not have this requirement; and that's where I was getting messed up.
$srcfiles = Get-ChildItem $bkpPath\* -exclude *.htm*, *.js, *.xml, *.ico would be the proper syntax in my example.

Resources