Changing directory to a folder matching a regex in powershell - regex

I want to CD into a folder that begins with the word "Patch", followed by several other digits. All I care about is that it begins with the word "Patch"
How can I change my directory using a regex in powershell?
This is what I have at the moment and it doesn't work. Am I on the right track though?
$FolderPath = "^Patch[0-9]+$"
cd "C:\Test\" + $FolderPath

To put you in the right direction:
Use Get-ChildItem and only get the directories matching your regex, something like:
$matchingItem = Get-ChildItem "C:\Test" -Directory | ?{ $_.Name -match $FolderPath } | select -First 1
Now you can cd to the matching directory.

You don't really need the regex. Wildcard blobbing will handle that:
cd c:\test\patch[0-9]*

Related

How to parse the folder path from a WMI process?

I need to be able to parse the folder path (which could vary) from an installed Windows service.
In PowerShell using
$serviceToRemove = Get-WmiObject -Class Win32_Service -Filter "name='Labelary'"
I can get the object, and if I do
$serviceToRemove.PathName
it gives
c:\program files\myapplicationname\mybinary.exe //rs/labelry
I need to get
c:\program files\myapplicationname
I've tried various combinations of splitting, but the path could vary or have spaces in it.
Is there a regex way of getting this portion of the path. The only guaranteed pattern is that I want the portion of the string which is before the wildcard *.exe . But I don't know how to express this in PowerShell. I tried \w*\.exe in a regex tester but this just returns the mybinary.exe.
Also various combinations of PowerShell or System.IO path tools seem to consider the //rs/labelry to be part of the path and thus not return the root correctly.
I would probably write it this way:
$pathName = Get-WmiObject Win32_Service -Filter "Name='Labelary'" |
Select-Object -ExpandProperty PathName |
Select-String '^"?(.+)\.exe' | ForEach-Object {
Split-Path $_.Matches[0].Groups[1].Value -Parent
}
Something like this should work:
$path = if ($serviceToRemove.PathName -match '[a-z]:\\.*?(?=\\[^\\]+\.exe)') {
$matches[0]
}
The regular expression matches a drive letter ([a-z]:\\) plus the shortest sequence of characters before a backslash followed by an executable name (\\[^\\]+\.exe). The positive lookahead assertion ((?=...)) ensures that the backslash and executable name are not included in the returned string.

Regex on Powershell script: Replace till end of line

I have some config files structured like:
PATH_KEY=C:\\dir\\project
foo=bar
I want to write a small script that replaces a certain key with current folder.
So basically I'm trying to replace "PATH_KEY=..." with "PATH_KEY=$PSScriptRoot"
My code so far:
$cfgs = Get-Childitem $PSScriptRoot -Filter *name*.cfg
foreach ($cfg in $cfgs)
{
( Get-Content $cfg) -replace 'PATH_KEY=.*?\n','PATH_KEY=$PSScriptRoot' | Set-Content $cfg
}
But the regular expression to take everything till end of line is not working.
Any help is appreciated!
You can use
'(?m)^PATH_KEY=.*'
or even
'PATH_KEY=.*'
Note that $ in the replacement should be doubled to denote a single $, but it is not a problem unless there is a digit after it.
See the demo:

Batch rename files with regex

I have a number of files with the following format:
name_name<number><number>[TIF<11 numbers>].jpg
e.g. john_sam01 [TIF 15355474840].jpg
And I would like to remove the [TIF 15355474840] from all of these files
This includes a leading space before the '[TIF...' and a different combination of 11 numbers each time.
So the previous example would become:
josh_sam01.jpg
In short, using powershell (or cmd.exe) with regex I would like to turn this filename:
josh_sam01 [TIF 15355474840].jpg
Into this:
josh_sam01.jpg
With variables being: 'john' 'sam' two numbers and the numbers after TIF.
Something like, with added newlines for clarity:
dir ‹parameters to select the set of files› |
% {
$newName = $_.Name -replace '\s\[TIF \d+\]',''
rename-item -newname $newName -literalPath $_.Fullname
}
Almost certainly adding -whatif to the rename until I was sure I had the file selection and rename correct.

Powershell Move file from directory to subdirectory based on filename

I would like to do all 8k+ files at once using the pattern since the left 5 chars of the file matches the right 5 of the sub-directory to move to.
This works one by one:
move-item -path X:\"Property Files"\05165*.pdf -destination X:\"Property Files"\"* -- 05165";
move-item -path X:\"Property Files"\05164*.pdf -destination X:\"Property Files"\"* -- 05164";
Thank you in advance for any help.
As a one-liner, assuming destination folder already exist:
Get-ChildItem "X:\Property Files\*.PDF" |
ForEach { move -path $_ -destination ($_.directoryname +"\* -- "+ $_.Name.substring(0,5))}
Using only the filename, you just extract the first five chars (substring(0,5)), then use it as the end of the folder to match.
$_.Directoryname assume destination folder is a subfolder of the source path.
Ok, you're on the right path with the whole RegEx tag here. What I did is look for everything until the last backslash, then captured 5 digits, then everything that isn't a backslash until the end of the line, and only returned the captured group. I set that as a variable $ItemNumber, and used that in the destination. I ran that on a ForEach loop for everything in the target source folder. Here's the code I ended up with:
ForEach($File in (GCI "X:\Property Files\*.PDF")){
$ItemNumber = $File.Fullname -replace ".+?\\(\d{5})[^\\]*$", "`$1"
move-item -path X:\"Property Files"\05165*.pdf -destination X:\"Property Files"\"* -- $ItemNumber"
}
You could do it through the pipe if you wanted, like this:
GCI "X:\Property Files\*.PDF"|%{move-item -path X:\"Property Files"\05165*.pdf -destination X:\"Property Files"\"* -- $($_.Fullname -replace ".+?\\(\d{5})[^\\]*$", "`$1")"}
But that gets kind of long, and some people really don't like that long of a single line.
That RegEx can be tested here, plus it breaks it all down. (link to regex101.com explanation)

Remove a substring from a filename with Powershell

In a deployment szenario, I need to rename config files. There are config files for every environment (Dev.Test, Dev.Prod, Integration, Prod). For example a web.config would be called web.Dev.Test.config if it was for the Dev.Test environment. On the target machine, I need to rename the files back to their original name (i.e. from web.Dev.Test.config to web.config) with Powershell.
$test = "web.Dev.Prod.config"
$environment = $test | Select-String -Pattern ".*\.(?<environment>(Dev.Test|Dev.Prod|Prod|Integration))\.config" | select -expand Matches | foreach {$_.groups["environment"].value}
if ($test -match "Dev.Prod")
{
$environment = "Dev.Prod"
}
$environment
$newFileName = $test.Remove($test.IndexOf($environment),$environment.Length + 1)
$newFileName
The problem I have with this is, that the Regex does not find the Dev.Prod evironment, but returns Prod instead. This is why I introduced the if statement. I was wondering if there was a more elegant way of renaming the files with Powershell.
Watch out for greedy matching. Modify your regex that starts ".*\.(?" to ".*?\.(?".