Tag Archives: cd

Return to Home with cd

I’ve been working in Git Bash a decent amount of my time recently, and I’ve found myself becoming used to using the cd command to return to my home directory (/c/Users/tommymaynard). Did you know you could do that? In that shell, as well as my Cygwin shell, it’s possible. I even fired up my Ubuntu Linux VM and tried it in the Terminal there, as well, and as expected, it works there too.

The cd alias in Windows PowerShell (that’s 5.1), which resolves to the Set-Location cmdlet, doesn’t do the same thing. Therefore, I made a quick modification to the Set-Location function I keep in my $PROFILE script. I’ll include it below, and then discuss it.

# Set-Location runs Push-Location, creates cd <blank> to $HOME (~).
Function Set-Location {
    Param (
        [string]$Path
    )

    If ($Path) {
        Push-Location -Path $Path
    } Else {
        Push-Location -Path ~
    }
}

My Set-Location function, just like the original cmdlet, accepts a path in order to know where in the file system to move the user. If the function is invoked without a path, however, it’ll now move the user to their $HOME directory (C:\Users\<username>\). So you’re aware, Push-Location puts the current location on the stack and then changes location to that which was specified. Again, it’ll move to $HOME, or ~, or C:\Users\<username>, which are all the same, if nothing is specified for the path parameter.

Here’s the a small portion of the help notes from the Push-Location cmdlet: “The Push-Location cmdlet adds, or pushes, the current location onto a location stack. If you specify a path, this cmdlet pushes the current location onto a location stack and then changes the current location to the location specified by the path.” Using my Set-Location function allows me to always use Pop-Location, or the popd alias, to return to my previous location in the file system.

In closing, I do want to mention that using cd by itself in PowerShell 6.0.2 on Windows, and PowerShell 6.0.0-alpha on Linux, works just like it does in Git Bash, Cygwin, and the Terminal on Ubuntu. Without an argument, it’ll automatically move you to your home directory, just like it does now, in my, Windows PowerShell 5.1.

Someone was paying attention.

Linux Prompt on Windows – Part I

I already have an answer to the question, “Why?” Because, I can. At some point in the last few days, I decided I would attempt to replicate the Linux prompt in PowerShell. So I did it, and I thought I would share it. I’ve broken this up a little with the full function toward the bottom of this evening’s post.

In this first section, we’ve created the prompt function’s basic structure and added our first bit of code. This code determines if the user that started the Windows PowerShell session is an administrator or not. If they are, they get the # symbol as part of the prompt, and if they’re not, they get the $ symbol.

Function Prompt {
    If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups -match 'S-1-5-32-544')) {
        $Symbol = '#'
    } Else {
        $Symbol = '$'
    }
}

The next addition includes the logic to determine how to write the path inside the prompt. If the current path is C:\Users\<CurrentUser>, it enters a tilde (~). If the path includes the C:\Users\<CurrentUser> path, in addition to one or more directories, it will enter a tilde and the other directory or directories, such as ~/Desktop, or ~/Favorites/Links. In the last case, it’ll simply list the current path after replacing the backslashes with forward slashes and dumping the drive letter and colon. In all instances, in fact, all (Windows) backslashes, will be replaced with (Unix/Linux) forward slashes.

Function Prompt {
    If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups -match 'S-1-5-32-544')) {
        $Symbol = '#'
    } Else {
        $Symbol = '$'
    }

    If ($PWD.Path -eq $env:USERPROFILE) {
        $Location = '~'
    } ElseIf ($PWD.Path -like "*$env:USERPROFILE*") {
        $Location = $PWD.Path -replace ($env:USERPROFILE -replace '\\','\\'),'~' -replace '\\','/'
    } Else {
        $Location = "$(($PWD.Path -replace '\\','/' -split ':')[-1])"
    }
}

The last section is where the prompt function actually writes the prompt to the screen. It’s the simple combination of the current user, an @ character, the computer name, the path, and the proper symbol (# or $). As you may notice, I’ve written the code to force the case of the current user and computer to lowercase.

Function Prompt {
    If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups -match 'S-1-5-32-544')) {
        $Symbol = '#'
    } Else {
        $Symbol = '$'
    }

    If ($PWD.Path -eq $env:USERPROFILE) {
        $Location = '~'
    } ElseIf ($PWD.Path -like "*$env:USERPROFILE*") {
        $Location = $PWD.Path -replace ($env:USERPROFILE -replace '\\','\\'),'~' -replace '\\','/'
    } Else {
        $Location = "$(($PWD.Path -replace '\\','/' -split ':')[-1])"
    }

    "$($env:USERNAME.ToLower())@$($env:COMPUTERNAME.ToLower()) $Location $Symbol "
}

In closing, I’ve included a gif of the prompt and an example of moving though the directory structure. While I typically only use full cmdlet names in my posts, this example does include aliases for the Set-Location cmdlet (cd, sl, and even chdir). Due to this function being saved in my profile script, this prompt displays immediately when a new console is opened, and every time after that. As someone that’s written a few different prompt functions, this one’s a keeper. I already can’t imaging switching back. On that note, you might not want to test it out.

duplicate-the-linux-prompt01

tommymaynard@srv01 / # $PWD.Path
C:\
tommymaynard@srv01 / # cd C:\Windows\
tommymaynard@srv01 /Windows # cd .\System32\
tommymaynard@srv01 /Windows/System32 # chdir ..
tommymaynard@srv01 /Windows # chdir ..
tommymaynard@srv01 / # sl /users
tommymaynard@srv01 /users # sl /users/tommymaynard2 # Not my current user.
tommymaynard@srv01 /users/tommymaynard2 # cd ..
tommymaynard@srv01 /users # cd C:\Users\tommymaynard\ # My current user.
tommymaynard@srv01 ~ # cd .\Desktop\
tommymaynard@srv01 ~/Desktop # cd ..
tommymaynard@srv01 ~ # cd .\Favorites\Links\
tommymaynard@srv01 ~/Favorites/Links # sl /
tommymaynard@srv01 / # cd /users
tommymaynard@srv01 /users # chdir \
tommymaynard@srv01 / #

Update1: A day later and I still love my new PowerShell prompt. I’ve made a minor change, however. The last line in the function is now the following three lines. It stores the prompt in a variable called $Prompt, modifies the title of the window to the $Prompt value, and then writes the prompt. In the past my window’s title indicate the computer name. Now it indicates that information, as well as the current user, the location on the current drive, and whether or not I’m running the session as an administrator.

...
	$Prompt = "$($env:USERNAME.ToLower())@$($env:COMPUTERNAME.ToLower()) $Location $Symbol "
	$Host.UI.RawUI.WindowTitle = $Prompt
	$Prompt
}

Update2: It occurred to me today that by entering the tilde character, such as Set-Location -Path ~, it moves you to the location stored in the Home property of the FileSystem PSProvider. Because of this, I opted to add another line, just before the beginning of the prompt function. Setting this property to $env:USERPROFILE, allows me to quickly move to C:\Users\<CurrentUser>. I should note that this property is sometimes already set. In those cases, this is just a precaution that the ~ character will move you back home.

(Get-PSProvider -PSProvider FileSystem).Home = $env:USERPROFILE
Function Prompt {
...
}

In case you want to take this prompt function for a spin, and you do, here’s everything. Copy and paste it to your console and hit Enter a couple times and try it out. If you hate it, close and reopen the PowerShell console and it never existed. Cheers.

(Get-PSProvider -PSProvider FileSystem).Home = $env:USERPROFILE
Function Prompt {
    If ([bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).Groups -match 'S-1-5-32-544')) {
        $Symbol = '#'
    } Else {
        $Symbol = '$'
    }
 
    If ($PWD.Path -eq $env:USERPROFILE) {
        $Location = '~'
    } ElseIf ($PWD.Path -like "*$env:USERPROFILE*") {
        $Location = $PWD.Path -replace ($env:USERPROFILE -replace '\\','\\'),'~' -replace '\\','/'
    } Else {
        $Location = "$(($PWD.Path -replace '\\','/' -split ':')[-1])"
    }

	$Prompt = "$($env:USERNAME.ToLower())@$($env:COMPUTERNAME.ToLower()) $Location $Symbol "
	$Host.UI.RawUI.WindowTitle = $Prompt
	$Prompt
}