1

I want to build a modular script that sorts files based on content (strings/Get-Content in PowerShell).

Requirement:

  1. Defining a directory. ($directory)

    start a foreach loop: foreach

  2. list items in the directory & full path in memory

    $FilePath in Get-ChildItem $directory | Select-Object -ExpandPropert FullName
    
  3. Load content of one file at a time in the memory

    $content = Get-Content $FilePath
    
  4. Search for the keyword and copy the file once a particular keyword is found.

    if ($content -match 'keyword1') { Copy-Item $FilePath $OutputPath }
    

While I am able to do this in a static manner using the below mentioned code, I wanted to modularise it for reuse.

[string] $Directory = "parth to source directory";
[string] $outpath1  = "outpath for keyword1";
[string] $OutputPath2 = "outpath for keyword2";
[string] $OutputPath3 = "outpath for keyword3";

foreach ($FilePath = Get-ChildItem $Directory | Select-Object -ExpandProperty FullName) {
    [string] $content = Get-Content $FilePath

    if ($content -match 'keyword1') {
        Copy-Item $FilePath $OutputPath
    } elseif ($content -match 'keyword2') {
        Copy-Item $FilePath $OutputPath2
    } else {
        Copy-Item $FilePath $keyword3
    }
}

My questions:

  1. Is it possible to define keywords in a single array? If so how do that in PowerShell? (keyword1, keyword2, keyword3)
  2. Run keywords sequentially in the files and whenever one keyword is detected, the file is copied to it's designated folder. Can I have this done in modular fashion or will I have to define directory for each keyword?

The reason I am doing this is because while the script is being used for 2 or 3 keywords as of now, it will be used for over 50 keywords and allowing reuse should help.

1
  • 1
    Write a function for a singular search and pass it the suitable parameters. If you are concerned about the foreach allow array input. See about_Arrays. Commented Aug 28, 2019 at 12:53

1 Answer 1

2

What you describe could be achieved with a hashtable and a nested loop:

$outpath = @{
    'keyword1' = 'outpath for keyword1'
    'keyword2' = 'outpath for keyword2'
    'keyword3' = 'outpath for keyword3'
}

foreach ($FilePath in Get-ChildItem $Directory | Select-Object -Expand FullName) {
    $content = Get-Content $FilePath

    foreach ($keyword in $outpath.Keys) {
        if ($content -match $keyword) {
            Copy-Item $FilePath $outpath[$keyword]
            break
        }
    }
}

Alternatively you could use a switch statement:

$outpath = @{
    'keyword1' = 'outpath for keyword1'
    'keyword2' = 'outpath for keyword2'
    'keyword3' = 'outpath for keyword3'
}

$pattern = ($outpath.Keys | ForEach-Object { [regex]::Escape($_) }) -join '|'

foreach ($FilePath in Get-ChildItem $Directory | Select-Object -Expand FullName) {
    $content = Get-Content $FilePath

    switch -regex ($content) {
        $pattern {
            Copy-Item $FilePath $outpath[$keyword]
            break
        }
    }
}

The latter would also give you a simple way of specifying a fallback destination path if you also want to handle files with no matching keyword.

$fallbackpath = '...'

foreach ($FilePath in Get-ChildItem $Directory | Select-Object -Expand FullName) {
    $content = Get-Content $FilePath

    switch -regex ($content) {
        $pattern {
            Copy-Item $FilePath $outpath[$keyword]
            break
        }
        default {
            Copy-Item $FilePath $fallbackpath
            break
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.