Use cd - in Powershell 7 to Return to Previous Directory

Introduction

A command that many shells have had forever and that PowerShell has had for a long time as well is ‘cd -’ which means “change directory to previous folder”. This means you could do something like this:

1
2
3
4
5
6
> cd c:\dev
c:\dev
> cd c:\temp
c:\temp
> cd -
c:\dev

This is quite handy in many situations. In particular, since I’ve modified my PowerShell Profile to NOT start in my users folder but instead to start in my c:\dev folder (from which I can easily get to any repo I may be working from), I very often find myself using cd - whenever I create a new terminal in the folder I want to be in such as when using VS Code.

The default behavior in VS Code when you say ‘New Terminal’ is to create it in the root of the folder that VS Code is running in. However in my case it always ends up being ‘c:\dev’ because of the aforementioned $PROFILE. This is easy enough for me to fix with… cd -. Works great. Less filling. That is until…

Upgrading to PowerShell 7 Breaks cd - Behavior

I recently upgraded to PowerShell 7 using something like this:

1
winget upgrade --id Microsoft.PowerShell

Once I did, I ran into issues with my oh-my-posh script. I tried upgrading oh-my-posh:

1
winget upgrade JanDeDobbeleer.OhMyPosh

But that didn’t fix the issue. I was getting errors like these when running . $PROFILE:

1
Get-PSReadLineKeyHandler : A positional parameter cannot be found that accepts argument 'Spacebar'. At C:\Users\USERNAME\AppData\Local\Packages\ohmyposh.cli_96v55e8n804z4\LocalCache\Local\oh-my-posh\init.14695981039346656037.ps1:421 char:18 + if ((Get-PSReadLineKeyHandler Spacebar).Function -eq 'OhM ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidArgument: (:) [Get-PSReadLineKeyHandler], ParameterBindingException + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.GetKeyHandlerCommand

It turns out there were a few problems. One I needed to change the instances of Get-PSReadLineKeyHandler Spacebar (and similar) to add -Chord and two I needed to upgrade my Get-PSReadLineKeyHandler because apparently it is NOT upgraded when you upgrade PowerShell.

So you check your version with this:

1
Get-Module PSReadLine -ListAvailable | Select Name, Version, Path

You want a version like 2.4.5 not 2.0.0.

To install a new version you use:

1
Install-Module PSReadLine -Scope CurrentUser -Force

Then after restarting PowerShell you should be able to run your profile without errors:

1
. $PROFILE

But none of that is related to the cd - breakage - that’s just new fun stuff you may run into as you upgrade PowerShell.

Fix CD - in PowerShell 7

To fix the cd - behavior you just need to add a custom function to your $PROFILE and make sure it’s being used, not the default alias. Also, use it to set your default starting folder if that’s a thing you do:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# Remove the built-in cd alias so our function takes over
if (Test-Path alias:cd) {
    Remove-Item alias:cd
}

# Enable using 'cd -' to return to previous location
function cd {
    param([string]$path = $HOME)

    if ($path -eq '-') {
        if ($global:OLDPWD) {
            $tmp = $PWD.Path
            Set-Location $global:OLDPWD
            $global:OLDPWD = $tmp
        } else {
            Write-Host "No previous directory found."
        }
        return
    }

    $global:OLDPWD = $PWD.Path

    if (Test-Path $path -PathType Container) {
        Set-Location $path
    }
    else {
        Write-Host "cd: path not found: $path"
    }
}

cd "C:\dev"

With this, I can now open up a terminal in VS Code and then type cd - to get back to the folder I want to be in.

Why Not Just Not Change Folders?

An even better solution, for those of you wondering, would be to not change folders when PowerShell is starting in some working folder where I actually want to be (like when VS Code or some AI agent does it), but to only use my preferred default location when PowerShell is being launched without a starting folder (and thus would drop me in my users folder).

To do that, all that’s needed is a small tweak to test to see where I am when PowerShell is starting, and only change if I happen to be in my users home folder:

1
2
3
4
# Only jump to C:\dev if we started in our home folder
if ($PWD.Path -ieq $HOME) {
    cd "C:\dev"
}

With this change, when I open a new terminal in VS Code, it stays in the proper folder, and when I create a new PowerShell window or tab, it starts in my default c:\dev folder. And either way, I can use cd - to navigate back from any folder I change to.

Side note, I also came across zoxide which is basically a super-powered cd replacement that works in all major shells. You can install it on windows with winget install ajeetdsouza.zoxide. I haven’t tried using it, yet, but it looks interesting for sure.

My Full $PROFILE

For anyone who cares and mostly for me on other/future machines, here’s my current full $PROFILE with these updates:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
oh-my-posh init pwsh | Invoke-Expression

# Chocolatey profile (unchanged)
$ChocolateyProfile = "$env:ChocolateyInstall\helpers\chocolateyProfile.psm1"
if (Test-Path($ChocolateyProfile)) {
  Import-Module "$ChocolateyProfile"
}

# Remove the built-in cd alias so our function takes over
if (Test-Path alias:cd) {
    Remove-Item alias:cd
}

# Enable using 'cd -' to return to previous location
function cd {
    param([string]$path = $HOME)

    if ($path -eq '-') {
        if ($global:OLDPWD) {
            $tmp = $PWD.Path
            Set-Location $global:OLDPWD
            $global:OLDPWD = $tmp
        } else {
            Write-Host "No previous directory found."
        }
        return
    }

    $global:OLDPWD = $PWD.Path

    if (Test-Path $path -PathType Container) {
        Set-Location $path
    }
    else {
        Write-Host "cd: path not found: $path"
    }
}

# Only jump to C:\dev if we started in our home folder
if ($PWD.Path -ieq $HOME) {
    cd "C:\dev"
}

Conclusion

PowerShell 7 broke the built-in cd - functionality, but it’s easy to restore with a custom function in your profile. The solution not only brings back this convenient navigation shortcut but also gives you fine-grained control over when PowerShell changes your starting directory. Whether you’re navigating between project folders or working with VS Code’s integrated terminal, these tweaks will make your PowerShell experience more efficient.

Resources