Nato Boram
Nato Boram

Reputation: 4973

How to prepend to a file in PowerShell?

I'm generating two files, userscript.meta.js and userscript.user.js. I need the output of userscript.meta.js to be placed at the very beginning of userscript.user.js.

Add-Content doesn't seem to accept a parameter to prepend and Get-Content | Set-Content will fail because userscript.user.js is being used by Get-Content.

I'd rather not create an intermediate file if it's physically possible to have a clean solution.

How to achieve this?

Upvotes: 10

Views: 4832

Answers (2)

Santiago Squarzon
Santiago Squarzon

Reputation: 60518

The Subexpression operator $( ) can evaluate both Get-Content statements which are then enumerated and passed through the pipeline to Set-Content:

$(
    Get-Content userscript.meta.js -Raw
    Get-Content userscript.user.js -Raw
) | Set-Content userscript.user.js

Consider using the Absolute Path of the files if your current directory is not where those files are.


An even more simplified approach than the above would be to put the paths in the desired order since both, the -Path and -LiteralPath parameters can take multiple values:

(Get-Content userscript.meta.js, userscript.user.js -Raw) |
    Set-Content userscript.user.js

And in case you want to get rid of excess leading or trailing white-space, you can include the String.Trim Method:

(Get-Content userscript.meta.js, userscript.user.js -Raw).Trim() |
    Set-Content userscript.user.js

Note that in above examples the grouping operator ( ) is mandatory as we need to consume all output from Get-Content before being passed through the pipeline to Set-Content. See Piping grouped expressions for more details.

Upvotes: 15

C. Tewalt
C. Tewalt

Reputation: 2509

For future folks, here's a snippet if you need to prepend the same thing to multiple files:

example: prepending an #include directive to a bunch of auto-generated C++ files so it works with my Windows environment.

Get-ChildItem -Path . -Filter *.cpp | ForEach-Object { 
    $file = $_.FullName

    # the -Raw param was important for me as it didn't read the entire
    # file properly without it. I even tried [System.IO.File]::ReadAllText
    # and got the same thing, so there must have been some characater that
    # caused the file read to return prematurely
    $content = Get-Content $file -Raw

    $prepend = '#include "stdafx.h"' + "`r`n"
    #this could also be from a file: aka
    # $prepend = Get-Content 'path_to_my_file_used_for_prepending'
    
    $content =  $prepend + $content
    Set-Content $file $content
}

Upvotes: 4

Related Questions