How can I test file existence using regular expressions - powershell

I want to test if the file C:\workspace\test_YYYYMMDD.txt, where YYYYMMDD means year, month, and date, exists on my disk.
How can I do this in PowerShell?
I know that test-path test_*.txt command returns true.
But test_*.txt also returns true when the file name is something like test_20170120asdf.txt, or test_2015cc1119aabb.txt.
I don't want file names like test_20170120asdf.txt being marked as true in test-path.
I'd like to apply regular expression test_\d{8}\.txt in test-path. How can I do this in PowerShell?

Something like:
gci C:\workspace\test_*.txt | ? {$_.Name -match '^test_\d{8}\.txt$'}

Wildcard expressions are much more limited in their matching abilities than regular expressions - see Get-Help about_Wildcards - but in this particular case they're enough:
Test-Path test_[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9].txt
If more sophisticated matching is needed, see LotPing's answer, which shows how to use regular expressions.

Related

Get-ChildItem with Multiple Paths via Variable

This one stumps me a bit. I generally feel pretty advanced in powershell but I simply dont understand the nuance of this one.
This works
$LogFiles = Get-ChildItem -Path c:\windows\temp\*.log,c:\temp\*.log,C:\programdata\Microsoft\IntuneManagementExtension\Logs\*.log
Yet what I want to do (and doesnt work) is this:
$LogsToGather = "c:\windows\temp\*.log,c:\temp\*.log,C:\programdata\Microsoft\IntuneManagementExtension\Logs\*.log"
$LogFiles = Get-ChildItem -Path "$($LogsToGather)" -Recurse
I have tried making the VAR an array, I have tried a number of things with making string. I was able to write around the issue but I am uniquely interested in understanding what data type -path is accepting with that common delineation and be able to create it dynamically.
It seems like a trick that the cmdlet accepts comma delineation. Can it be recreated using some sort of array, hashtable, etc..?
Anyone know?
Yes, $LogsToGather must be an array of strings for your command to work:
$LogsToGather = 'c:\windows\temp\*.log', 'c:\temp\*.log', 'C:\programdata\Microsoft\IntuneManagementExtension\Logs\*.log'
Note how the array elements, separated by ,, must be quoted individually (see bottom section).
Get-Help with -Parameter is a quick way to examine the data type a given parameter expects:
PS> Get-Help Get-ChildItem -Parameter Path
-Path <String[]>
Specifies a path to one or more locations. Wildcards are permitted. The default location is the current directory (`.`).
Required? false
Position? 0
Default value Current directory
Accept pipeline input? True (ByPropertyName, ByValue)
Accept wildcard characters? false
String[] represents an array ([]) of [string] (System.String) instances - see about_Command_Syntax.
For more information on Get-ChildItem, see the docs.
As for what you tried:
$LogsToGather = "c:\windows\temp\*.log,c:\temp\*.log,C:\programdata\Microsoft\IntuneManagementExtension\Logs\*.log"
This creates a single string that, when passed to Get-ChildItem, is as a whole interpreted as a single path, which obviously won't work.
Note that specifying the elements of an array unquoted, as in:
Get-ChildItem -path c:\windows\temp\*.log, c:\temp\*.log, ...
is only supported if you pass an array as a command argument, not in the context of creating an array with an expression such as $LogsToGather = 'foo', 'bar', ..
The reason is that PowerShell has two fundamental parsing modes - argument mode and expression mode, as explained in this answer,

Return True if two patterns are found in text with Powershell

This seems like a simple task but I can't seem to get it to work. I want to be able to read a text file and if two exact patterns are found return True. If it only finds one then it returns false.
I tried this, but it is not working:
Get-Content $log_path | Select-String -pattern "\bInstallation of\b|\bfailed\b" -AllMatches -quiet
What can I try next?
Your pattern contained a or | statement which basically says.
If one or the other (Installation or failed) is present, then it's a match.
What you want is to use a wildcard instead so both word and the in-between are part of the same match.
Select-String -pattern "\bInstallation .* failed\b" -quiet
Additional Notes
When having issues, there are online regex tester to allow you to test your regular expression.
I personally like a lot RegexHero even though you need IE because it is done in Silverlight because it has an Analyze section for your regular expression which breaks down your expression and gives an explanation in words of what you are doing.
Super useful when learning or just when dealing with always more complex epxressions.
For instance, your initial regular expression.
Although I did not personally used it, RegexStorm also looks promising and is not IE restricted.

powershell -match Unexpect Results

i've written a simple PowerShell script that is designed to take a file name and then move the file into a particular folder.
The files in question are forms scanned in as PDF documents.
Within the file name, I have defined a unique string of characters used to help identify which form it is and then my script will sort the file into the correct folder.
I've captured the file name as a string variable.
I am using -match to evaluate the file name string variable and my issue is that match is acting like...well -like.
For example, my script looks for (F1) in the string and if this returns true my script will move the file into a folder named IT Account Requests.
This all works well until my script finds a file with (F10) in the name, as 'match' will evaluate the string and find a match for F1 also.
How can I use 'match' to return true for an exact string block?
I know this may sound like a fairly basic newbie question to ask, but how do I use -match to tell the different between the two file types?
I've scoured the web looking to learn how to force -match to do what I would like but maybe I need a re-think here and use something other than 'match' to gain the result I need?
I appreciate your time reading this.
Code Example:
$Master_File_name = "Hardware Request (F10).pdf"
if ($Master_File_name -match "(F1)"){Write-Output "yes"}
if ($Master_File_name -match "(F10)"){Write-Output "yes"}
Both if statements return 'yes'
-match does a regular expression based match against your string, meaning that the right-hand side argument is a regex pattern, not a literal string.
In regex, (F1) means "match on F and 1, and capture the substring as a separate group".
To match on the literal string (F1), escape the pattern either manually:
if($Master_File_Name -match '\(F1\)'){Write-Output 'yes'}
or have it done for you automatically using the Regex.Escape() method:
if($Master_File_Name -match [regex]::Escape('(F1)')){Write-Output 'yes'}

What is the FileSystem provider filter syntax?

Get-Help Get-ChildItem displays -Filter parameter, with displayed wording "Specifies a filter in the provider's format or language". That language differs between what Powershell calls "providers", and file system is declared as one of them. But I have not found any syntax descriptions on file system provider's filter syntax. Any help?
The filter syntax supported by the FileSystem provider is sparsely (if it all) documented, probably because there's nothing much to say.
In short, it only supports simple wildcard matching as you know it from Windows XP-era Search:
Any file with an extension:
*.*
Any file with the .txt extension:
*.txt
Partial wildcard matching:
*something*.txt
Single-character matching (matches myfile1.jpg but not myfile01.jpg):
myfile?.*
Simple character sets (this matches bear and beer):
be[ae]r
Simple character ranges (this matches filea.txt, fileb.txt and filec.txt):
file[a-c].txt
Note: It only supports a single expression per filter, so this is illegal:
*.jpg|*.txt

How can I filter filename patterns in PowerShell?

I need to do something similar to Unix's ls | grep 'my[rR]egexp?' in Powershell. The similar expression ls | Select-String -Pattern 'my[rR]egexp?' seems to go through contents of the listed files, rather than simply filtering the filenames themselves.
The Select-String documentation hasn't been of much help either.
Very simple:
ls | where Name -match 'myregex'
There are other options, though:
(ls) -match 'myregex'
Or, depending on how complex your regex is, you could maybe also solve it with a simple wildcard match:
ls wild[ck]ard*.txt
which is faster than above options. And if you can get it into a wildcard match without character classes you can also just use the -Filter parameter to Get-ChildItem (ls), which performs filtering on the file system level and thus is even faster. Note also that PowerShell is case-insensitive by default, so a character class like [rR] is unnecessary.
While researching based on #Joey's answer, I stumbled upon another way to achieve the same (based on Select-String itself):
ls -Name | Select-String -Pattern 'my[Rr]egexp?'
The -Name argument seems to make ls return the result as a plain string rather than FileInfo object, so Select-String treats it as the string to be searched in rather than a list of files to be searched.