Powershell find a file in root dir with excludes - powershell

I have the following code to try locating a folder within my project.
$rootDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$fileName = "Scripts*"
$paths = gci -path $rootDir -filter $fileName -Recurse | Select-Object -Expand FullName
The problem I am having is that I don't want it finding the folder inside of bin or obj folder. Is there a way to exclude those from the search?
Basically I need to recursively search my solution folder for a folder name, excluding the bin/obj locations.
When I try using the -Exclude it gives my compile errors. I imagine there has to be a easier way than this to do it.

I think the problem is that -Exclude only accepts strings. You'll need to use Where-Object to filter out multiple strings.
$paths = gci -path $rootDir -filter $fileName -Recurse | Where-Object {$_.FullName -notlike "*bin*\*" -and $_.FullName -notlike "*obj*\*"} | Select-Object -Expand FullName

The problem is that the -Exclude is passed along to the Provider, and the file system provider is not good at filtering in general. I would suggest using a Where clause and using one of the -Match operators (-inotmatch is a case insensitive inverted match, so it excludes anything that matches the text) like this:
$rootDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$fileName = "Scripts*"
$paths = gci -path $rootDir -filter $filename -Recurse | Select-Object -Expand FullName | ?{$_ -inotmatch "\\(bin|obj)\\"}
That looks for a string that starts with a backslash (), followed by either bin or obj, and trailed by another backslash.

Related

Powershell Get-ChildItem Exclude Default Windows Folders

I want to search for files with .2fa extension on remote computers. I can find the files I want, but it takes a long time to get to the second computer because it scans all windows files.
I tried the -exclude and where arguments but they do not work.
Could you please help me? Thanks.
$ServerList = Import-Csv 'C:\PC.CSV'
$result = foreach ($pc in $ServerList.barkod) {
$exclude = '*ProgramData*','*Program Files*','*Program Files (x86)*','*Windows*'.'*winupdate*'
$sourcepath = 'c$'
Get-ChildItem -Path \\$pc\$sourcepath -Recurse | Where-Object { $_.Name -like "*.2fa" } |
where {$_.name -notin $Exclude}
}
$result
I tried
-Exclude $exclude
-where {$_.name -notin $Exclude}
-exclude doesn't work with subdirectories or -filter:
Get-ChildItem -Path \\$pc\$sourcepath\ -exclude $exclude |
get-childitem -recurse -filter *.2fa
Since you are looking for files with a certain extension, use the -Filter parameter.
This will be the fastest option to search for only .2fa files, disregarding all others. (Filter works on the Name property)
If you want to search the C: drive, you are bound to hit Access Denied exceptions and because to exclude a list of foldernames using post-process with a Where-Object clause,
Get-ChildItem will try and search in these folders you need to apend -ErrorAction SilentlyContinue to the command
$exclude = 'ProgramData','Program Files','Program Files (x86)','Windows'.'winupdate'
# create a regex string you can use with the `-notmatch` operator
# each item will be Regex Escaped and joined together with the OR symbol '|'
$excludeThese = ($exclude | ForEach-Object { [Regex]::Escape($_) }) -join '|'
$ServerList = (Import-Csv 'C:\PC.CSV').barkod
$sourcepath = 'c$'
$result = foreach ($pc in $ServerList) {
Get-ChildItem -Path "\\$pc\$sourcepath" -Filter '*.2fa' -File -Recurse -ErrorAction SilentlyContinue |
Where-Object {$_.DirectoryName -notmatch $excludeThese}
}
$result

Powershell how to filter Get-ChildItem with a multiple values

I need to get-children items a directory and find to a specific named zip file.
I don't know to zip file's name. But one thing that I know the zip file includes a date. And I have to find full path of zip from that date. I mean like:
xxxx_20220810.zip
or
xxxx20220810.zip
I check this topic powershell Get-ChildItem given multiple -Filters but this page doesn't help me.
$date = (Get-Date).ToString('yyyyMMdd')
$zipPath = Get-ChildItem -Path $path -Filter '*.zip' -Recurse| % { $_.FullName -match $date}
$zipPath = Get-ChildItem -Path $path -Filter '*.zip' -Recurse| % { $_.FullName -contains $date}
What you're asking for can still be expressed as a single filter expression:
$date = (Get-Date).ToString('yyyyMMdd')
$zipPath = Get-ChildItem -Path $path -Filter "*${date}*.zip" -Recurse
-Filter only accepts a single pattern, so if you do need to filter against any of a number of conflicting patterns, you'll still have to use Where-Object:
Get-ChildItem -Path $path -Filter *.zip -Recurse |Where-Object {
$_.BaseName -like "*${year}*${month}*${day}*" -or $_.BaseName -like "*${year}*${day}*${month}*"
}

Get ChildItem from only files of specific folders

I try to export files of specific named Folders:
Get-ChildItem -Path 'C:\Test' -Name -Recurse -File > C:\Test\Test.txt
I get a list like:
content.csv
Test.txt
Folder 1\INTERESTED_FOLDER\a - Kopie.txt
Folder 1\INTERESTED_FOLDER\a.txt
Folder 1\Neuer Ordner\ttt.txt
Folder 1\Neuer Ordner - Kopie\ttt.txt
Folder 2\INTERESTED_FOLDER\b - Kopie.txt
Folder 2\INTERESTED_FOLDER\b.txt
Folder 2\Neuer Ordner\ttt.txt
Folder 2\Neuer Ordner - Kopie\ttt.txt
But what i want is:
Folder 1\INTERESTED_FOLDER\a - Kopie.txt
Folder 1\INTERESTED_FOLDER\a.txt
Folder 2\INTERESTED_FOLDER\b - Kopie.txt
Folder 2\INTERESTED_FOLDER\b.txt
I tried with -Filter "INTERESTED" etc. but then i only get
C:\Test\Folder 1\INTERESTED_FOLDER
C:\Test\Folder 2\INTERESTED_FOLDER
What i do wrong?
If I read your question correctly, you want the FullNames of the files (so their names including the path).
If that is the case, remove the -Name switch and filter on the DirectoryName property like:
(Get-ChildItem -Path 'C:\Test' -Recurse -File |
Where-Object { $_.DirectoryName -match 'INTERESTED_FOLDER' }).FullName | # also matches 'MY_INTERESTED_FOLDER_123'
Set-Content -Path 'C:\Test\Test.txt'
Alternatives for the Where-Object clause:
# also matches 'MY_INTERESTED_FOLDER_123'
Where-Object { $_.DirectoryName -like '*INTERESTED_FOLDER*' }
or if you are looking for a precise match on the complete folder name
# does NOT match 'MY_INTERESTED_FOLDER_123'
Where-Object { $_.DirectoryName -split '[/\\]' -contains 'INTERESTED_FOLDER' }
You can perform a wildcard search using the -Filter parameter:
Get-ChildItem -Path 'C:\Test' -Name -Recurse -File -Filter *INTERESTED_FOLDER* > C:\Test\Test.txt
If for example, you were interested in finding the files in INTERESTED_FOLDER but also only the files that are .txt you could do:
-Filter *INTERESTED_FOLDER*.txt
Using the -Name parameter affects your capabilities because you are returning strings instead of FileInfoObjects. You may then use Where-Object to capture everything.
Get-ChildItem -Path 'C:\Test' -Name -Recurse -File |
Where {$_ -match '\\INTERESTED_FOLDER\\'} |
Set-Content c:\test\test.txt
Note that the matching above assumes INTERESTED_FOLDER is not a direct descendent of your path. If that is a possibility, then your match expression needs to be updated to \\?INTERESTED_FOLDER\\.

Get contents of subfolders containing a string in their name

I want to get all files in subfolders, of the same root folder, that all contain the same string ("foo") in the name of the subfolder(s). Below gives me no error, and no output. I don't know what I'm missing.
Get-ChildItem $rootfolder | where {$_.Attributes -eq 'Directory' -and $_.BaseName -contains 'foo'}) | echo $file
Ultimately, I would like to not just echo their names, but move each file to a target folder.
Thank you.
Here is a solution that includes moving the child files of each folder to a new target folder:
$RootFolder = '.'
$TargetFolder = '.\Test'
Get-ChildItem $RootFolder | Where-Object {$_.PSIsContainer -and $_.BaseName -match 'foo'} |
ForEach-Object { Get-ChildItem $_.FullName |
ForEach-Object { Move-Item $_.FullName $TargetFolder -WhatIf } }
Remove -WhatIf when you are happy it's doing what it should be.
You might need to modify the Get-ChildItem $_.FullName part if you (for example) want to exclude sub-directories of the folders, or if you want to include child items in all subfolders of those paths, but not the folders themselves.
replace
Get-ChildItem $rootfolder | where {$_.Attributes -match 'Directory' -and $_.basename -Match 'foo'}) | echo $file
with
Get-ChildItem $rootfolder | where {($_.Attributes -eq 'Directory') -and ($_.basename -like '*foo*')} | Move-Item $targetPath
your request:
that all contain the same string ("foo")
you have to use the -like comparison operator. Also for exact match I would use -eq (case sensitive version is -ceq) instead of -match since its used for matching substrings and patterns.
workflow:
Gets all the files in directory, sending it through pipe to Where-Object cmdlet where you are filtering based on properties Attributes and Basename. When the filtering is done, its being sent to cmdlet Move-Item.
Adapt the first two vars to your environment.
$rootfolder = 'C:\Test'
$target = 'X:\path\to\whereever'
Get-ChildItem $rootfolder -Filter '*foo*' |
Where {$_.PSiscontainer} |
ForEach-Object {
"Processing folder: {0} " -f $_
Move $_\* -Destination $target
}

How can I check a pdb for a particular dll exists in a directory using Powershell?

I have a parent Directory inside which there are multiple project folders.
How can I check in powershell whether a pdb exists for all the respective dlls inside all the project folders?
I tried the below but dont know how to match a pdb with the particular dll.
$source = "C:\ParentDir\*"
$Dir = get-childitem $source -recurse
$List = $Dir | where-object {$_.Name -like "*.dll"}
Any help will be greatly appreciated.
Try this, it should output two columns, FullName, the dll path, and PDB which contains a boolean value indicating if there's a corresponding PDB file.
Get-ChildItem $source -Filter *.dll -Recurse |
Select-Object FullName,#{n='PDB';e={ Test-Path ($_.FullName -replace 'dll$','pdb') -PathType Leaf }}
Try this:
$source = ".\Projects\"
$dlls = Get-ChildItem -Path $source -Filter *.dll -Recurse | where {!$_.PSIsContainer}
foreach ($dll in $dlls)
{
$pdb = $dll.FullName.Replace(".dll",".pdb")
if (!(Test-Path $pdb)) { Write-Output $dll }
}
It returns the fileinfo(dir) objects for every every dll that doesn't have a pdb. use fullname property to get filepath. I provided the long answer above so to easily show how it works. To shorten it, use:
$source = ".\Projects\"
Get-ChildItem -Path $source -Filter *.dll -Recurse | where {!$_.PSIsContainer} | % { $pdb = $_.FullName.Replace(".dll",".pdb"); if (!(Test-Path $pdb)) { $_ } }