1

I am trying to replace certain lines in a file that doesnt match the condition and then i need to write the output to a diff file [ I actually need the output to be redirected to the same file, but i dont know how to do it] and get the below error

Code -

   $fileName = E:\onlinecode\afarm_2106.txt
  $FileModified = @() 
 [System.IO.StreamReader]$afarmfile = [System.IO.File]::Open("E:\onlinecode\Btnbar64\a_farm.txt", 
 [System.IO.FileMode]::Open)
while (-not $afarmfile.EndOfStream){
$line = $afarmfile.ReadLine()
     if ( $Line -like "*2104 Training Markets*" ) 
            {  
              $FileModified += $Line 
              # Write-Output $FileModified
             }
            else
            {         
             $FileModified += $Line -replace "2104","2106" -replace "21043","21062"
            
            }
      }
 $afarmfile.Close() 
 Set-Content -Path $filename -value $FileModified 

Error -

 Set-Content : Cannot bind argument to parameter 'Path' because it is null.
 At line:19 char:19
+ Set-Content -Path $filename -value $FileModified
+                   ~~~~~~~~~
+ CategoryInfo          : InvalidData: (:) [Set-Content], ParameterBindingValidationException
+ FullyQualifiedErrorId : 
ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.SetContentCommand

Any help to resolve the issue / Directly write to the same file would be appreciated

wehelpdox
  • 339
  • 6
  • 16

2 Answers2

3

Why not use switch ?

$fileIn  = 'E:\onlinecode\Btnbar64\a_farm.txt'
$fileOut = 'E:\onlinecode\afarm_2106.txt'  # or use the same filename of $fileIn to overwrite

# loop through the file line-by-line and capture the results in variable $fileModified
$fileModified = switch -Regex -File $fileIn {
    '2104 Training Markets' { 
        # don't change this line, just output unchanged
        $_
    }
    default {
        # output the line with certain strings replaced
        $_ -replace '2104','2106' -replace '21043','21062'
    }
}

$fileModified | Set-Content -Path $fileOut -Force

Instead of switch -Regex -File $fileIn {..} you could also do

switch -Wildcard -File $fileIn {..}

In that case, replace the condition to '*2104 Training Markets*'

Theo
  • 57,719
  • 8
  • 24
  • 41
3

Consider using Theo's improved solution, but just to point out what the immediate problem was:

The RHS of your $fileName = assignment lacked quoting:

# WRONG: Lack of quoting of the RHS string value.
#        This *opens the file in a text editor* and assigns $null to $fileName
$fileName = E:\onlinecode\afarm_2106.txt

Unlike in shells such as cmd.exe or bash, assigning string values to variables requires quoting in PowerShell.

Since your path is a literal value, it's best to use single-quoting:

# OK - string must be *quoted*.
$fileName = 'E:\onlinecode\afarm_2106.txt'

See the bottom section of this answer for an overview of PowerShell's string literals.

Note that the need for quoting strings applies to all forms of assignments, including to properties, possibly as part of a hashtable or custom-object literal (e.g., @{ foo = 'bar' } or [pscustomobject] @{ foo = 'bar' }.


Background information:

PowerShell has two fundamental parsing modes, argument mode (like a shell) and expression mode (like a programming language).

It is the first character (on the RHS of =, in this case) that determines which mode is entered, and since your value started neither with ', ", $, @, (, [, nor {, argument mode was entered, and your - unquoted - file path was interpreted as a command.

PowerShell accepts a file path for execution even if the file isn't itself executable, in which case it asks the GUI shell to open the file, as if you had double-clicked it in File Explorer on Windows, for instance.

Therefore, an unquoted .txt file path will open in your system's default text editor, and this operation will (a) be asynchronous and (b) produce no output.

Conversely, if your file path needs quoting due to spaces and/or is based on variables, yet you do want to execute it as a command, use &, the call operator; e.g. & 'E:\online code\afarm_2106.txt'

As a result, $fileName was assigned no value, which effectively made it $null.[1]


[1] Strictly speaking, the "automation null" value is assigned, [System.Management.Automation.Internal.AutomationNull]::Value, which, however, behaves like $null in most contexts.
See GitHub issue #13465 for a discussion of when it does not, and why distinguishing the two via -is [AutomationNull] should therefore be supported.

mklement0
  • 382,024
  • 64
  • 607
  • 775