Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Say you went to PowerShell and added a path:

$env:path += 'C:\banal\cranial\inversion'

Oops, you forgot a ; in it, it should have been

$env:path += ';C:\banal\cranial\inversion'

-- but your path is already screwed up. In zsh, we can just vared PATH; what about PowerShell, is there a way to edit the variable instead of resetting it anew? And if resetting, how can you copy and paste just a part of it, if it wraps around?

share|improve this question
    
The zsh builtin is called vared rather than varedit. –  Dennis Williamson Jan 22 '11 at 4:33
    
of course; context switching... fixed –  Alexy Khrabrov Jan 22 '11 at 5:00

2 Answers 2

up vote 1 down vote accepted

It doesn't, but you could do something like:

    function Edit-Variable {
#.Parameter name
#    The name (or path) to the variable to edit.
#.Parameter Environment
#    Optional switch to force evaluating the name as an environment variable. You don't need this if you specify the path as env:Path instead of just "Path"
#.Example
#     Edit-Variable -env path
#.Example
#     Edit-Variable profile
#.Example
#     Edit-Variable env:\path
#.Example
#     Edit-Variable variable:profile

param(
    [Parameter(Position=0,ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)]
    [string]$name
,
    [switch]$Environment
)
process {
    $path = Resolve-Path $name -ErrorAction SilentlyContinue
    if($Environment) {
        ## Force Env: if they said -Env
        if(!$path -or $Path.Provider.Name -ne "Environment") {
            $path = Resolve-Path "Env:$name"
        }
    } else {
        if($Path -and $Path.Provider.Name -eq "Environment") {
            $Environment = $true
        } elseif(!$path -or $Path.Provider.Name -ne "Variable") {
            $path = Resolve-Path "Variable:$name" -ErrorAction SilentlyContinue
        }
    }

    $temp = [IO.Path]::GetTempFileName()
    if($path) {
        if(!$Environment) {
            $value = (Get-Variable $path.ProviderPath).Value
            $string = $value -is [String]
            if(!$string) {
                Write-Warning "Variable $name is not a string variable, editing as CliXml"
                Export-Clixml $temp -InputObject $Value 
            } else {
                Set-Content $temp $Value
            }
        } else {
            Get-Content $path | Set-Content $temp
        }
    } else {
        $Environment = $false
        New-Variable $Name
        $path = Resolve-Path Variable:$name -ErrorAction SilentlyContinue
    }
    if(!$path) {
        Write-Error "Cannot find variable '$name' because it does not exist."
    } else {
        # Let the user edit it in notepad, and see if they save it
        $pre = Get-ChildItem $temp
        (Start-Process notepad $temp -passthru).WaitForExit()
        $post = Get-ChildItem $temp
        if($post.LastWriteTime -gt $pre.LastWriteTime) {
            if(!$Environment) {
                if(!$string) {
                    Import-CliXml $temp | Set-Variable $path.ProviderPath
                } else {
                    Get-Content $temp | Set-Variable $path.ProviderPath
                }
            } else {
                Get-Content $temp | Set-Content $path
            }
        }
    }
    Remove-Item $temp -ErrorAction SilentlyContinue
}
}

Set-Alias vared Edit-Variable

I know that's not how zsh's works, but notepad was handy...

share|improve this answer
    
Very interesting! Alas, pasting this into PS 2.0 and then saying, vared env:path causes a warning that it's not a string variable, editing as CliXml -- and then the notepad shows a <Nil /> wrapped in <Objs ...>. –  Alexy Khrabrov Jan 22 '11 at 5:03
    
try vared -env path or vared path -env ... I made the env a switch: it works with environment variables, and regular variables (and anything else with content, really). I thought about requiring vared profile and vared env:path and just detecting the drive to see that it was env, but in the end, I went with the switch. I should have put an example in, I'll fix that. –  Jaykul Jan 22 '11 at 6:08
    
OK, I totally redid the error handling, so now you can do either one you like: Edit-Variable env:path or Edit-Variable -env path –  Jaykul Jan 22 '11 at 6:41

you could use the string methods to accomplish the correction

$indexError = $env:Path.LastIndexOf("C:")
$env:Path = $env:Path.remove($indexError, 1)
$env:Path = $env.Insert($indexError, ";C")

Don't forget that in powershell everything is an object, and you could use any programming strategies to achieve what you need.

share|improve this answer
    
this is very useful as well! as soon as I'm able I'll up it –  Alexy Khrabrov Jan 26 '11 at 4:33
    
Yeah, it's totally true that you could handle this with simple script. Personally, I'd go for $Env:Path = $Env:Path -replace '(?<!;)C:',';C:' # replace C: that doesn't follow a ; with ';C:' –  Jaykul Feb 2 '11 at 18:26
    
@jaykul very nice what you did, i wan't to learn more, what is the subject name to search further? –  mjsr Feb 7 '11 at 17:42
    
It's a regular expression: specifically, that is a negative look-behind zero-width assertion. regular-expressions.info/lookaround.html –  Jaykul Feb 8 '11 at 3:02

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.