Home > Mobile >  Powershell Foreach construction remove text in multiple files
Powershell Foreach construction remove text in multiple files

Time:04-14

As newby to powershell I googled a long time to make a piece that can remove a part of text in a single file based upon some variables like this. The text section can be anywhere within the file. And that specific section needs to be removed.

<#
#create test file
$file = "c:\users\public\Test\remove.txt"
Set-Content $file (1..100) -Force
$content = Get-Content $file
#>
$file = Get-Content "c:\users\public\Test\remove.txt"
$StartText= '50'
$EndText= "75"
$LineNumberStart= $file | Select-string -Pattern $StartText
$Start = $linenumberStart.LineNumber
$LineNumberEnd= $file | Select-string -Pattern $EndText
$End = $linenumberEnd.LineNumber
$keep = $file[0..$Start]   $file[$End..($file.Count - 1)]
$keep | Set-Content "c:\users\public\test\remove.txt"

Now I would like have to the above working functionality but on all files in a particular folder. However, for the reason "Expressions are only allowed as the first element of a pipeline." I can't get it to work with this piece of code below:

$ReportPath = Split-Path -Parent $Script:MyInvocation.MyCommand.Path
$StartText= "50"
$EndText= "75"
Get-ChildItem -Path $ReportPath -Filter *.txt | ForEach {  (Get-Content $_.PSPath) | 
$LineNumberStart= $_ | Select-string -Pattern $StartText
$Start = $LineNumberStart.LineNumber
$LineNumberEnd= $_ | Select-string -Pattern $EndText
$End = $LineNumberEnd.LineNumber
$keep = $_[0..$Start]   $_[$End..($_.Count - 1)]
$keep|Set-Content $_.PSPath
}

Expected outcome is that all files in the folder have the middle section of the text file removed.

Can someone please assist in getting this foreach construction resolved?

CodePudding user response:

I would recommend you to use a switch for this use case, if I understand correctly you're looking to start skipping the lines of a file from where the line matches the value of $StartText and stop skipping after the line matches the value of $EndText. If that's the case, here is a minimal example of how you can do this using a switch statement with the -Regex parameter:

$StartText = '50'
$EndText = '75'
$skip = $false

switch -Regex (0..100) {
    $StartText { $skip = $true; continue }
    $EndText { $skip = $false; continue }
    { $skip } { continue }
    default { $_ }
}

If this is what you expected, then if you want to the same for each file, the code would look like this, note the use of -File to read each file content:

$StartText = '50'
$EndText = '75'
$skip = $false

Get-ChildItem -Path $ReportPath -Filter *.txt | ForEach-Object {
    & {
        switch -Regex -File ($_.FullName) {
            $StartText { $skip = $true; continue }
            $EndText { $skip = $false; continue }
            { $skip } { continue }
            default { $_ }
        }
    } | Set-Content ($_.BaseName   '-New'   $_.Extension)
}
  • Related