Check a value against an array with wildcards?

This topic contains 6 replies, has 3 voices, and was last updated by  Tony Pagliaro 1 year, 10 months ago.

  • Author
    Posts
  • #31337

    Tony Pagliaro
    Participant

    I have a script that runs on a folder and searches for files based on a cultivated list of keywords. The file names are never the same, but they always contain the same keywords. The files need to be moved to a given location, that list is also cultivated (given).

    For instance, a file named "the.tps.report_383-202-5321.csv" would always contain "TPS" and "report" but might sometimes be separated by a hyphen, space, or whatever. I have the table containing strings with wildcards, such as "*tps*report*". The target folders also have wildcards, but my issue concerns the keywords.

    So I made a custom table with properties "keyword" and "Target Folder" and I have my data in there without issue. I am basically filtering down to select only the files I want to move, they are stored in subfolders (one level). My logic here would be: computer, find files with this keyword, and move those into the target folder that matches with it.

        $SourcePaths = Resolve-Path -Path "$Complete\*" |
            where {$_.Path -notmatch '(\\_)'}  # define folder(s), ignore ones starting with underscore
    
        $Keywords = ($Table.Keyword)
        $SourceFiles = Get-ChildItem -literalpath $SourcePaths |
        Where {$_.Extension -in $FileTypes} |
        Where {$_.Name -notlike "*sample*"} |
        where {$_.Name -like $Keywords}  # This is the PROBLEM I have #
    
    # ...then I would move those $SourceFiles. 
    

    The filetypes filter works because there are no wildcards in that array.
    The name/keyword filter doesn't return any data, I assume because it's not evaluating the wildcards.

    How do I check a value against a collection of things with wildcards?
    Oh yeah, the filenames often contain [square brackets], which is why I use literalpath.

    I won't be back to reply on any comments until tmrw (FYI). Thanks!

  • #31338

    Curtis Smith
    Participant

    use Regular Expression and the -match operator

    $keywords = ".*tps.*report.*|.*somethingelse.*report.*"
    Get-ChildItem | Where-Object {$_.Name -match $keywords}

  • #31342

    Tony Pagliaro
    Participant

    This right here shows I need to keep practicing my regex skills. TIL the dot is the real wildcard. Thanks for the reply.

    The matching works now, but it doesn't solve that whole array problem I have. Your long string of OR operators does the trick, but in the end I am moving files into folders based on those keywords, so I am using a table with values, and that's where I get stuck.

    Basically I need to know if this is possible or not, and what my options are. If I have a couple of arrays:

    $a = @(
    '.*red.*',
    '.*blue.*',
    '.*green.*yellow.*'
    )
    
    $s = @(
    'orangeredyellow',
    'orangegreenblack',
    'orangegreenredblackyellow',
    'orangeblueblack',
    'brownblackblack'
    )
    

    Should I be able to filter out the 2nd and last entry of $s by matching it with $a?

    PS D:\ps> $a
    .*red.*
    .*blue.*
    .*green.*yellow.*
    PS D:\ps> $s
    orangeredyellow
    orangegreenblack
    orangegreenredblackyellow
    orangeblueblack
    brownblackblue
    PS D:\ps> $s -match $a 
    PS D:\ps> 
    

    I cannot. Even if I use a trusty foreach loop.

    PS D:\ps> $S | foreach { $_ -match $a }
    False
    False
    False
    False
    False
    PS D:\ps> 
    
  • #31346

    Kamil Tatar
    Participant

    Hi Tony,

    Try to remove . (dot) from $a array and use:

    
    $a = @(
    '*red*',
    '*blue*',
    '*green*yellow*'
    )
    
    #loop
    foreach ($x in $s) { foreach ($y in $a) { $x -like $y} }
    

    Result should look like this:

    PS> foreach ($x in $s) { foreach ($y in $a) { $x -like $y} }
    True
    False
    False
    False
    False
    False
    True
    False
    True
    False
    True
    False
    False
    False
    False
    
  • #31360

    Curtis Smith
    Participant
    $a = @(
    '.*red.*',
    '.*blue.*',
    '.*green.*yellow.*'
    )
    
    $s = @(
    'orangeredyellow',
    'orangegreenblack',
    'orangegreenredblackyellow',
    'orangeblueblack',
    'brownblackblack'
    )
    
    $s -match ($a -join "|")
    

    Results:

    orangeredyellow
    orangegreenredblackyellow
    orangeblueblack

  • #31384

    Curtis Smith
    Participant

    Another example

    $a = @(
    '.*red.*',
    '.*blue.*',
    '.*green.*yellow.*'
    )
    
    $s = @(
    'orangeredyellow',
    'orangegreenblack',
    'orangegreenredblackyellow',
    'orangeblueblack',
    'brownblackblack'
    )
    "-------------------------------------------------------------------------"
    $s -match ($a -join "|")
    "-------------------------------------------------------------------------"
    $s -match $a[0] | ForEach-Object { "$_ move to folder red" }
    "-------------------------------------------------------------------------"
    $s -match $a[1] | ForEach-Object { "$_ move to folder blue" }
    "-------------------------------------------------------------------------"
    $s -match $a[2] | ForEach-Object { "$_ move to folder green and yellow" }
    "-------------------------------------------------------------------------"
    

    Results:
    ————————————————————————-
    orangeredyellow
    orangegreenredblackyellow
    orangeblueblack
    ————————————————————————-
    orangeredyellow move to folder red
    orangegreenredblackyellow move to folder red
    ————————————————————————-
    orangeblueblack move to folder blue
    ————————————————————————-
    orangegreenredblackyellow move to folder green and yellow
    ————————————————————————-

  • #31386

    Tony Pagliaro
    Participant

    Thanks Kamil, I had wanted to avoid the nested loop for better readability.

    Curtis, thanks again, this will work. It's one of those 'why didn't i think of that' moments... 🙂

You must be logged in to reply to this topic.