Skip to content
This repository was archived by the owner on Mar 5, 2025. It is now read-only.
This repository was archived by the owner on Mar 5, 2025. It is now read-only.

Add Edit-File command #19

Open
Open
@rkeithhill

Description

@rkeithhill

I would really love to see this command added. PS has been missing an easy way to modify files since v1. This comes in so handy for build systems. Our builds, first thing, edit a number of files to modify version numbers using this command e.g.:

# Update C# interop assembly version
Edit-FileContent -Path (Join-Path $rootPath 'src/Adapters/Acme.Wiley.Coyote.Api/Acme.Wiley.Coyote.Api.csproj') `
    -Pattern '(?<=\<Version\>)(.*?)(?=\</Version\>)' `
    -Replacement "${wileyVersion}.0"
Edit-FileContent -Path (Join-Path $rootPath 'src/Adapters/Acme.Wiley.Coyote.Api/Acme.Wiley.Coyote.Api.csproj') `
    -Pattern '(?<=\<InformationalVersion\>)(.*?)(?=\</InformationalVersion\>)' `
    -Replacement "${wileyVersion}${suffix}"

# WileyClient Conan C++ Support
Edit-FileContent -Path (Join-Path $rootPath 'src/WileyClient/conanfile.py') `
    -Pattern '(?<= version\s*=\s*'')(.*?)(?='')' `
    -Replacement "${wileyVersion}${suffix}"

# WileyManagement Conan C++ Support
Edit-FileContent -Path (Join-Path $rootPath 'src/WileyManagement/conanfile.py') `
    -Pattern '(?<= version\s*=\s*'')(.*?)(?='')' `
    -Replacement "${wileyVersion}${suffix}"
Edit-FileContent -Path (Join-Path $rootPath 'src/WileyManagement/conanfile.py') `
    -Pattern '(?<=WileyClient/)(.*?)(?=@Acme)' `
    -Replacement "${wileyVersion}${suffix}"

# NuGet C# Support
Edit-FileContent -Path (Join-Path $rootPath 'build/NuGet/WileyClientPkg/Acme.Wiley.Coyote.Api.nuspec') `
    -Pattern '(?<=\<version\>)(.*?)(?=\</version\>)' `
    -Replacement "${wileyVersion}${suffix}"
Edit-FileContent -Path (Join-Path $rootPath 'build/NuGet/WileyClientPkg/Acme.Wiley.Coyote.Api.nuspec') `
    -Pattern '(?<=id="runtime\.native\.Acme\.Wiley\.Coyote\.Api"\s+version=")(.*?)(?=")' `
    -Replacement "${wileyVersion}${suffix}"
Edit-FileContent -Path (Join-Path $rootPath 'build/NuGet/runtime.native.WileyClientPkg/runtime.native.Acme.Wiley.Coyote.Api.nuspec') `
    -Pattern '(?<=\<version\>)(.*?)(?=\</version\>)' `
    -Replacement "${wileyVersion}${suffix}"

# API Help Docs
$regexForHelpDocs = if ($Final) { '(?<== ")(\d)(.\d)*-?.* PRELIMINARY(?=")' } else { '(?<== ")(\d)(.\d)*-?.*(?= PRELIMINARY")' }
Edit-FileContent -Path (Join-Path $rootPath 'doc/CppReference/wiley-cpp-doxyfile') `
    -Pattern $regexForHelpDocs `
    -Replacement "${wileyVersion}${suffix}"

And here's the implementation - feel free to use as much (or little) as you want. https://github.com/Pscx/Pscx/blob/master/Src/Pscx/Commands/IO/EditFileCommand.cs

Activity

rkeithhill

rkeithhill commented on Nov 25, 2020

@rkeithhill
Author

OK, I'm taking a swag at importing the PSCX EditFileCommand.cs. Hopefully will have a PR soon-ish.

SteveL-MSFT

SteveL-MSFT commented on Nov 25, 2020

@SteveL-MSFT
Member

Should it just be Edit-Content to match the other *-Content cmdlets? It could accept text via pipeline and also allow editing?

AdilHindistan

AdilHindistan commented on Nov 25, 2020

@AdilHindistan

I needed this once or twice and used something like (gc {file}) -replace {pattern}, {replacement} | out-file ...to do that. This would be a nice shortcut.

rkeithhill

rkeithhill commented on Nov 25, 2020

@rkeithhill
Author

I'm fine with Edit-Content. The main thing we were trying to avoid is this approach:

Get-Content foo.csproj | % { $_ -replace $pattern,$replacement } | Set-Content foo.csproj

Where you have the file locking problem (trying to write to file while reading it) as well as this doesn't preserve the file's original encoding which should be a goal of this command. Anway, the above pattern is common enough to warrant a simpler form:

Edit-Content foo.csproj $pattern $replacement
rkeithhill

rkeithhill commented on Nov 25, 2020

@rkeithhill
Author

Hmm, the PSCX implementation has an elaborate way of supporting Path/LiteralPath that won't port over. @SteveL-MSFT is there a canonical sample of Path/LiteralPath C# code I can use?

rkeithhill

rkeithhill commented on Nov 26, 2020

@rkeithhill
Author

@SteveL-MSFT Do you think this cmdlet should derive from ContentCommandBase? If not, I can't quite use that code as-is since it calls down into a base class to suppress wildcard expansion. And if yes, won't that require -Include and -Filter parameters which wouldn't make so much sense for this cmdlet.

To be honest, the implementation of the functionality isn't too bad but dealing with Path/LiteralPath parameters has been such a PITA that @oising added easier handling for these parameters in PSCX in the form of PscxPathInfo (see https://github.com/Pscx/Pscx/blob/master/Src/Pscx.Core/Commands/PscxPathCommandBase.cs)

SteveL-MSFT

SteveL-MSFT commented on Nov 26, 2020

@SteveL-MSFT
Member
rkeithhill

rkeithhill commented on Dec 5, 2020

@rkeithhill
Author

@SteveL-MSFT Thanks. That got me past the Path/LiteralPath parameter issue. I have something that compiles and runs. However, I had to copy over some crufty PSCX code for the Encoding parameter (to do string conversion, checks, etc). I'm hopeful I can find some more modern and hopefully SMA built-in support. Do you have any pointers for that? I could submit a PR now but ... I'd rather have better Encoding parameter support implemented first.

FYI the command's default behavior is to try to preserve the file's original encoding so the -Encoding parameter isn't normally needed unless you also want to change the file's encoding.

rkeithhill

rkeithhill commented on Dec 7, 2020

@rkeithhill
Author

@SteveL-MSFT OK found some code in Out-File.cs but ... the Encoding parameter support required me to copy a number of internal classes. Sigh... In order to support "easier to write", "more consistent & correcrt" parameter handling in C# cmdlets (and even script cmdlets), more of these "internal" classes need to be made public.

FWIW I'm not a big fan of how some of this is implemented e.g. deriving from ContentCommandBase.cs to get Path/LiteralPath handling. We did something similar in PSCX and when it worked it was nice but there were a number of cases where it didn't work. So, the answer probably isn't to just make existing internal classes public. It would be better to provide "parameter implementations" that folks can use & configure via attributes (or interfaces). Two very good parameters to start with would be Path and LiteralPath.

Anyway, I should have an initial WIP PR out in a few days.

added this to the 1.0 Consider milestone on Jul 25, 2023
SteveL-MSFT

SteveL-MSFT commented on Jul 25, 2023

@SteveL-MSFT
Member

We may choose to include Jim's version and call it Edit-TextFile as there have been asks to edit other file types.

gwojan

gwojan commented on Aug 9, 2024

@gwojan

We may choose to include Jim's version and call it Edit-TextFile as there have been asks to edit other file types.

@SteveL-MSFT is there any status on this being included? Other than Jim's brief demo during one of the PowerShell Community calls I seem to have lost track of this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

      Development

      Participants

      @AdilHindistan@rkeithhill@gwojan@SteveL-MSFT

      Issue actions

        Add Edit-File command · Issue #19 · PowerShell/TextUtility