Author Posts

August 20, 2015 at 8:35 am

Hi,

I would like to do a get-childitem but set up a regex that says only to select files whose name is in all capitals.

e.g.
ERROR.LOG
OUTPUT.TXT
FOO.BAR
but not
FOO.bar
error.LOG
etc.

Any ideas? many thanks

August 20, 2015 at 9:02 am

You can try something like the following, the procedure of which can be described as:

"Get all child items where the base name and file extension both match a regex that contains the character class [A-Z] (In the case of the second regex, I include a period after the caret character because the Extension property of a Child Item includes the period as the first character in the string.

 Get-Childitem | 
    Where-Object {
        ($_.BaseName -cmatch '^[A-Z]+$') -and 
        ($_.Extension -cmatch '^.[A-Z]+$') }

There are probably shorter ways to get this done, but the key points are using -cmatch instead of -match in order to enforce case sensitivity, and making sure you are checking the correct properties of each child item.

August 20, 2015 at 9:05 am

So basically what you really want is file names that don't have lower case letters in them. Here is a snippet using your sample file names.

$list = @"
ERROR.LOG
OUTPUT.TXT
FOO.BAR
FOO.bar
error.LOG
"@ -split "`r`n"
$list | foreach {
    if ($_ -cnotmatch "[a-z]")
    {
        "$_"
    }
}

Or using Get-ChildItem ...

Get-ChildItem -File | foreach {
    if ($_ -cnotmatch "[a-z]") { "$_" }
}

August 20, 2015 at 9:16 am

Good call Bob, it's faster to check for the non-existence of lowercase characters, like in your examples.

Measure-Command {Get-ChildItem -File | foreach {
    if ($_ -cnotmatch "[a-z]") { "$_" }
}}

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 2
Ticks             : 28345
TotalDays         : 3.2806712962963E-08
TotalHours        : 7.87361111111111E-07
TotalMinutes      : 4.72416666666667E-05
TotalSeconds      : 0.0028345
TotalMilliseconds : 2.8345
Measure-Command {Get-Childitem | 
    Where-Object {
        ($_.BaseName -cmatch '^[A-Z]+$') -and 
        ($_.Extension -cmatch '^.[A-Z]+$') }}

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 4
Ticks             : 43857
TotalDays         : 5.07604166666667E-08
TotalHours        : 1.21825E-06
TotalMinutes      : 7.3095E-05
TotalSeconds      : 0.0043857
TotalMilliseconds : 4.3857

August 22, 2015 at 5:13 am

nice one guys... that's great and it works...
Quick one... I haven't seen $_ before on its own... versus using $_.xxx. Does this then check across the full contents of the string ?

August 22, 2015 at 9:32 am

It all depends on what $_ represents in the pipeline. At all times it means the current object in the pipeline. And that may be a simple string object (as in the case above), an array, a hash table, a multiple-property object (like a file system or process object), or whatever. It's up to you as the scripter to know what $_ represents. To that end, Get-Member is your best friend!