Author Posts

October 26, 2015 at 2:45 pm

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!

October 26, 2015 at 5:36 pm

use Regular Expression and the -match operator

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

October 26, 2015 at 7:19 pm

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> 

October 27, 2015 at 12:51 am

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

October 27, 2015 at 7:20 am

$a = @(
'.*red.*',
'.*blue.*',
'.*green.*yellow.*'
)

$s = @(
'orangeredyellow',
'orangegreenblack',
'orangegreenredblackyellow',
'orangeblueblack',
'brownblackblack'
)

$s -match ($a -join "|")

Results:

orangeredyellow
orangegreenredblackyellow
orangeblueblack

October 27, 2015 at 1:09 pm

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
————————————————————————-

October 27, 2015 at 3:26 pm

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... 🙂