PowerShell Filter on multiple parameters - powershell

I was wondering if is possible to specify multiple search filters as once. For example, I have this line of code that finds all files that have the "&" symbol.
get-childitem ./ -Recurse -Filter "*&*" |
? { $_.PSIsContainer } |
Select-Object -Property FullName
I'd like to extend this so that I can search one time and find files with other symbols like %,$,#, etc. I want to find files that have any of these symbols, not neccesarly files that have all of them so I assume there needs to be an OR somewhere. I tried the below code but it didn't seem to work for me:
get-childitem ./ -Recurse -Filter "*&*" -Filter "%" |
? { $_.PSIsContainer } |
Select-Object -Property FullName

You can use the -match operator and a regex for this:
Get-ChildItem -Recurse |
Where { !$_.PSIsContainer -and ($_.name -match '&|%|\$|#')} |
Select-Object -Property FullName
If you are on PowerShell v3 or higher you can simplify this a bit:
Get-ChildItem -Recurse -File |
Where Name -match '&|%|\$|#' |
Select-Object -Property FullName

If you have V3 or better, you can leverage the "globbing" wildcard feature:
get-childitem './*[&%$#]*' -Recurse | where {$_.PSIsContainer}
If you've got V4, you can dispense with the $_.PSIsContainer filter and use the -Directory switch:
get-childitem './*[&%$#]*' -Recurse -Directory

Related

Using PowerShell Where-Object not working with Get-ChildItem

I am trying to get directories that contain "COO", but after adding the Where-Object nothing is returned, the script is looping through each of the folders but nothing makes it to the file when the Where-Object is in place.
This works:
Get-ChildItem -Path $path -Recurse -Directory | select Fullname | Export-csv c:users\shay\desktop\test.csv
This doesn't:
Get-ChildItem -Path $path -Recurse -Directory | Select Fullname | Where-Object {$_.Fullname -like 'COO'} | Export-Csv c:users\shay\desktop\test.csv
In order to use the -Like parameter you'll need to include a wildcard (*), try the following:
Get-ChildItem -Path $path -Recurse -Directory | select Fullname | where-object {$_.Fullname -like '*COO*'} | Export-csv c:users\shay\desktop\test.csv
You could also potentially move the expression to the Get-ChildItem portion of this snippet.
Get-ChildItem -Path $path -Recurse -Directory -Filter '*COO*' | select Fullname | Export-csv c:users\shay\desktop\test.csv

Select folder names with a common word

I am trying to get the profile folders of the user User1 but don't want User10 folders from a directory.
Here is what I have tried:
Get-ChildItem -Path "$Profilesroot" -Recurse -Filter "*User1*"
and the out put shows User1, User1.v1, User10, User10.v1 folders
Same out put for the for the following:
Get-ChildItem "$profilesroot" -Recurse | Select-String -Pattern "User1"
Get-ChildItem "$profilesroot" -Recurse | Where {$_.Name -match 'User1'}
Get-ChildItem "$profilesroot" -Recurse | Where {$_.Name -like '*User1*'}
If I try the following, I am getting the required output but I feel there is a better option:
Get-ChildItem $profiles -Recurse | Where {$_.Name -like 'User1'}
Get-ChildItem $profiles -Recurse | Where {$_.Name -like 'User1.*'}
Apologies if the ask was not clear.
If you use Get-ChildItem's -Include parameter instead of -Filter, you can pass multiple PowerShell wildcard expressions.
Note:
Use of -Include is generally slower than use of -Filter, because the latter filters at the source, whereas -Include collects all items and then filters. Conversely, the -Include uses PowerShell's wildcard expressions, and not the more limited ones supported by -Filter, which are additionally saddled with legacy quirks.
However, a single Get-ChildItem call still outperforms a Get-ChildItem -Recurse ... | Where-Object { ... } pipeline.
That is - generally speaking - use something like
Get-ChildItem -Recurse ... | Where-Object { $_.Name -match '^User1\b' }, as suggested by Mathias R. Jessen, only if you truly need the enhanced matching flexibility that -match, the regular expression-based string-matching operator, provides.
If you're really looking for matching directories at all levels of the $ProfilesRoot subtree (-Recurse), use the following:
Get-ChildItem $ProfilesRoot -Recurse -Directory -Include User1, User1.*
If, by contrast, you're just looking for matching directories located directly in $ProfilesRoot:
Get-ChildItem $ProfilesRoot\* -Directory -Include User1, User1.*
Note the addition of \* to the (positionally implied) -Path argument, because in the absence of -Recurse -Include is unexpectedly only applied to the input path itself, not its children - see this answer for a detailed discussion of this counterintuitive behavior.
To get user's profile path, you should rely on operating system, but not on path concatenation.
$path = #(Get-WmiObject -Class 'Win32_UserProfile' |
Where-Object { $_.Special -eq $false } |
Where-Object { -not [string]::IsNullOrWhiteSpace($_.LocalPath) } |
Where-Object { $_.LocalPath.EndsWith("\User1") } |
Select-Object -ExpandProperty 'LocalPath' )[0]
More accurate way, because
sometimes profile path not matches username
sometimes profile path matches other user's name
sometimes profile path is not in profileroot
sometimes user have more than one profile and some of this profiles are broken and not used by user.
$path = #(Get-WmiObject -Class 'Win32_UserProfile' |
Where-Object { $_.Special -eq $false } |
Where-Object { -not [string]::IsNullOrWhiteSpace($_.LocalPath) } |
Where-Object { $_.SID -eq ([System.Security.Principal.NTAccount]('User1')).Translate([System.Security.Principal.SecurityIdentifier]).ToString() } |
Select-Object -ExpandProperty 'LocalPath' )[0]
Even more accurate way using SID matching and WMI filtering
$userSid = ([System.Security.Principal.NTAccount]('User1')).Translate([System.Security.Principal.SecurityIdentifier]).ToString()
$path = #(Get-WmiObject -Class 'Win32_UserProfile' -Filter "(Special = FALSE) AND (LocalPath LIKE '%\\%') AND (SID = '$($userSid)')" -Property #('LocalPath'))[0].LocalPath

Finding Files in a directory equal to 0 Powershell

I was wondering how I can display a list of empty files in a directory
$test = gci "C:\Users\Freedom\Documents" -Recurse
$test | Where-Object {$_.PsISContainer} | Select-Object FullName | Where-Object {$_.GetFiles() -eq 0}
I Don't understand because when I do get-childitem | get-member I get a list of properties and methods I can use and in the list is getfiles() why can't I use this method why's it giving me an error message?
Method invocation failed because [System.IO.FileInfo] does not contain a method named 'GetFiles'.
I think you want this:
Get-ChildItem | Where-Object { (-not $_.PSIsContainer) -and ($_.Length -eq 0) }
If you have PowerShell 3.0 or later you can use this:
Get-ChildItem -File | Where-Object { $_.Length -eq 0 }
Of course you can add whatever other parameters for Get-ChildItem that you want (-Recurse, etc.).
Wow I had what I wanted mixed up! And I had to add the .count to the getfiles() method
$test | Where-Object {$_.PsISContainer} | Where-Object {$_.GetFiles().Count -eq 0} | Select-Object FullName
try this
Get-ChildItem "c:\temp" -File -Recurse | where Length -eq 0
Use Get-ChildItem and the File flag, -Recurse is needed to get every file in the folder and in the folder below. Then get all the files were Get-Content returns null.
Get-ChildItem $YourPath -Recurse -File | Where-Object {!(Get-Content $_.Fullname)}

Recursively looking for count of file extension using PowerShell

Looking to get a PowerShell snippet that will list all file extensions recursively in a folder along with the count.
/abc/(1).cfc
/abc/john/(265).cfm, (1).html
/abc/john/js/(25).js
/abc/john/css/(6).css
This is what I've tried so far, but I'm not sure how to add the path for each:
Get-Childitem "C:\projects\newfolder\edit" -Recurse |
where { -not $_.PSIsContainer } |
group Extension -NoElement |
sort count -Desc
The answer posted by #AnsgarWiechers is OK if you want the list of matching files as well as the count; if you only want the directory name and the count,
(Powershell v2:)
Get-ChildItem 'C:\projects\newfolder\edit' -Recurse |
Where-Object { -not $_.PSIsContainer } |
Group-Object DirectoryName, Extension |
Select-Object Name, Count
(PowerShell v3+:)
Get-ChildItem 'C:\projects\newfolder\edit' -Recurse -File |
Group-Object DirectoryName, Extension |
Select-Object Name, Count
You can group by multiple criteria:
Get-ChildItem 'C:\projects\newfolder\edit' -Recurse |
Where-Object { -not $_.PSIsContainer } |
Group-Object DirectoryName, Extension
On PowerShell v3 and newer the filtering can be done directly with Get-ChildItem:
Get-ChildItem 'C:\projects\newfolder\edit' -Recurse -File |
Group-Object DirectoryName, Extension
You can use the following script to achieve the expected output:
Get-ChildItem "C:\TempFiles" -Recurse -File | Group-Object DirectoryName |
ForEach-Object {
"{0}\{1}" -f $_.Name,
(($_.Group | Group-Object Extension |
ForEach-Object { ("({0}){1}" -f $_.Count, $_.Name) }) -join ",")
}
Output
C:\TempFiles\Root\(1).json,(2).html,(2).txt
C:\TempFiles\Root\Folder1\(4).json,(2).html,(2).txt,(2).png
C:\TempFiles\Root\Folder1\Folder1-1\(2).json,(2).html
C:\TempFiles\Root\Folder2\(2).txt

How exploit Get-ChildItem result?

I would like list all path to go to folder name ending with "_S" recursively.
I did that:
Get-ChildItem -Recurse | Where-Object {($_.Attributes -match "Directory") -and ($_.Name.EndsWith("_S") -and ($_.PSIsContainer -eq 1))}
But the result isn't an array. How i can to exploit the results ?
My goal is to have something like that:
Myfolder\folder1\folder1_S
Myfolder\folder2_S
Use Select-Object and grab the FullName of the file.
Also, as stated in the comments on the question by #Paul ($_.Attributes -match "Directory") and ($_.PSIsContainer -eq 1) is redundant, might want to remove one of them.
Get-ChildItem -Recurse | Where-Object {($_.Attributes -match "Directory") -and ($_.Name.EndsWith("_S"))} | Select-Object -ExpandProperty FullName
The above can also be refactored in PowerShell 3.0+, to
Get-ChildItem -Recurse -Directory -Filter *_S | Select-Object -ExpandProperty FullName
which would recursively get the path of all directories ending with "_S"