sashang
sashang

Reputation: 12234

Windows PowerShell: changing the command prompt

Using Windows PowerShell, how do I change the command prompt?

For example, the default prompt says

PS C:\Documents and Settings\govendes\My Documents>

I want to customize that string.

Upvotes: 111

Views: 82943

Answers (8)

Patrick Burwell
Patrick Burwell

Reputation: 171

PROMPT in PowerShell

A better way to track the path, while keeping the hostname and logging time/date in every line run:

function prompt {
    $dateTime = get-date -Format "dd.MM.yyyy HH:mm:ss"
    $currentDirectory = $(Get-Location)
    $UncRoot = $currentDirectory.Drive.DisplayRoot
    write-host "$dateTime" -NoNewline -ForegroundColor YELLOW
    write-host " $UncRoot" -ForegroundColor White
    # Convert-Path needed for pure UNC-locations
    write-host "$ENV:COMPUTERNAME-PS:$(Convert-Path $currentDirectory)>" -NoNewline -ForegroundColor GREEN
    return " "
}

...and you get:

myservername-C:\Users\myusername\Documents\WindowsPowerShell\scripts>

Finally! :)

Upvotes: 1

StefanGreve
StefanGreve

Reputation: 171

PowerShell Prompt

In case someone is looking for a more sophisticated answer, here's my PowerShell v7 prompt that I have developed over the course of a year. To put it into context, it's part of my personal PowerShell profile:

https://github.com/StefanGreve/profile

Disclaimer

The easiest way to get a fancy PowerShell prompt up and running is to use established solutions created by the pwsh community, so if you just need something that works with few lines of code to write on your end, you might want to take a look at this project:

https://github.com/dahlbyk/posh-git

However, if you are like me and want to write your own custom prompt from scratch, then the code snippets below might be able to give you some ideas on how to approach this problem.

Custom Prompt

I will break down the most important pieces here. To start things of, I added the necessary code to determine the current platform we are on (since some bits are OS-specific and I also use this function on Unix-based operating systems):

enum OS
{
    Unknown = 0
    Windows = 1
    Linux = 2
    MacOS = 3
}

# I map these booleans to an Enum so that I can switch over them
$global:OperatingSystem = if ([OperatingSystem]::IsWindows()) {
    [OS]::Windows
} elseif ([OperatingSystem]::IsLinux()) {
    [OS]::Linux
} elseif ([OperatingSystem]::IsMacOS()) {
    [OS]::MacOS
} else {
    [OS]::Unknown
}

# In the prompt function below this is used to toggle the leading char ('>' or '#') to indicate elevated privilages
if ([OperatingSystem]::IsWindows()) {
    $global:IsAdmin = ([Principal.WindowsPrincipal][Principal.WindowsIdentity]::GetCurrent()).IsInRole([Principal.WindowsBuiltInRole]::Administrator)
}

if ([OperatingSystem]::IsLinux()) {
    $global:IsAdmin = $(id -u) -eq 0
}
# Required for Python if you want to set the venv indicator in the terminal yourself, else skip this part
$env:VIRTUAL_ENV_DISABLE_PROMPT = 1
# Returns the execution time of the last command you ran, or 0 on init
function Get-ExecutionTime {
    $History = Get-History
    $ExecTime = $History ? ($History[-1].EndExecutionTime - $History[-1].StartExecutionTime) : (New-TimeSpan)
    Write-Output $ExecTime
}

After the build up, we can continue to dive into the actual prompt function:

function prompt {
    $ExecTime = Get-ExecutionTime

    # Only show the current branch if we are inside a Git repository. Notice that the Git command writes to stderr if we are not inside a Git repository
    $Branch = if ($(git rev-parse --is-inside-work-tree 2>&1) -eq $true) {
          # If you version of git doesn't support the --show-current flag yet, use this command instead:
          # git rev-parse --abbrev-ref HEAD
          # It's less readable so I opted for the more modern approach but you may want to use the command above if using the latest versions of programs isn't your thing
          [string]::Format(" {0}({1}){2}", $PSStyle.Foreground.Blue, $(git branch --show-current), $PSStyle.Foreground.White)
    }

    # You can delete this part if you don't use Python, it is used to indicate whether a virtual environment is active
    $Venv = if ($env:VIRTUAL_ENV) {
        [string]::Format(" {0}({1}){2}", $PSStyle.Foreground.Magenta, [Path]::GetFileName($env:VIRTUAL_ENV), $PSStyle.Foreground.White)
    }

    $Computer = switch ($global:OperatingSystem) {
        ([OS]::Windows) {
            [PSCustomObject]@{
                UserName = $env:USERNAME
                HostName = $env:COMPUTERNAME
            }
        }
        ([OS]::Linux) {
            [PSCustomObject]@{
                UserName = $env:USER
                HostName = hostname
            }
        }
        ([OS]::MacOS) {
            # I don't have a Mac so I cannot guarantee that this bit works, but in theory it should do the trick based on what I found online
            [PSCustomObject]@{
                UserName = id -un
                HostName = scutil --get ComputerName
            }
        }
    }

    return [System.Collections.ArrayList]@(
        "[",
        $PSStyle.Foreground.BrightCyan,
        $Computer.UserName,
        $PSStyle.Foreground.White,
        "@",
        $Computer.HostName,
        " ",
        $PSStyle.Foreground.Green,
        [DirectoryInfo]::new($ExecutionContext.SessionState.Path.CurrentLocation).BaseName,
        $PSStyle.Foreground.White,
        "]",
        " ",
        $PSStyle.Foreground.Yellow,
        "(",
        $ExecTime.Hours.ToString("D2"),
        ":",
        $ExecTime.Minutes.ToString("D2"),
        ":",
        $ExecTime.Seconds.ToString("D2"),
        ":",
        $ExecTime.Milliseconds.ToString("D3"),
        ")",
        $PSStyle.Foreground.White,
        $Branch,
        $Venv, # (you may want to remove this line, see remark above)
        "`n",
        [string]::new($global:IsAdmin ? "#" : ">", $NestedPromptLevel + 1),
        " "
    ) -join ""
}

Upvotes: 4

Chris Horan
Chris Horan

Reputation: 151

To just show the drive letter I use:

function prompt {(get-location).drive.name+"\...>"}

Then to revert to the path I use:

function prompt {"$pwd>"}

Upvotes: 10

Trivia Coder
Trivia Coder

Reputation: 141

At the prompt, I like a current timestamp and resolved drive letters for network drives. To make it more readable, I put it in two lines, and played a bit with colors.

With CMD, I ended up with

PROMPT=$E[33m$D$T$H$H$H$S$E[37m$M$_$E[1m$P$G

For PowerShell, I got the same result with:

function prompt {
    $dateTime = get-date -Format "dd.MM.yyyy HH:mm:ss"
    $currentDirectory = $(Get-Location)
    $UncRoot = $currentDirectory.Drive.DisplayRoot

    write-host "$dateTime" -NoNewline -ForegroundColor White
    write-host " $UncRoot" -ForegroundColor Gray
    # Convert-Path needed for pure UNC-locations
    write-host "PS $(Convert-Path $currentDirectory)>" -NoNewline -ForegroundColor Yellow
    return " "
}

Which is a little more readable :-)

BTW:

  • I prefer powershell_ise.exe $PROFILE instead of (dumb) Notepad.
  • If you like to debug your prompt() with breakpoints, you should rename the prompt-function to anything else (or try it in another file). Otherwise you might end up in a loop: When you stop debugging, prompt() is called again and you stop at the breakpoint, again. Quite irritating, at first...

Upvotes: 14

Warren Stevens
Warren Stevens

Reputation: 1067

Related to a comment to Ocaso Protal's answer, the following is needed for Windows Server 2012 as well as Windows 7 (in a PowerShell window):

new-item -itemtype file -path $profile -force
notepad $PROFILE

I would suggest the following as a prompt if you run with multiple user names (e.g. yourself + a production login):

function Global:prompt {"PS [$Env:username]$PWD`n>"} 

(Credit goes to David I. McIntosh for this one.)

Upvotes: 30

Ocaso Protal
Ocaso Protal

Reputation: 20267

Just put the function prompt in your PowerShell profile (notepad $PROFILE), e.g.:

function prompt {"PS: $(get-date)>"}

or colored:

function prompt
{
    Write-Host ("PS " + $(get-date) +">") -nonewline -foregroundcolor White
    return " "
}

Upvotes: 139

nudls00p
nudls00p

Reputation: 521

This version of Warren Stevens' answer avoids the noisy "Microsoft.PowerShell.Core\FileSystem" in the path if you Set-Location to network shares.

function prompt {"PS [$Env:username@$Env:computername]$($PWD.ProviderPath)`n> "} 

Upvotes: 7

Fomentia
Fomentia

Reputation: 994

If you want to do it yourself, then Ocaso Protal's answer is the way to go. But if you're lazy like me and just want something to do it for you, then I highly recommend Luke Sampson's Pshazz package.

Just to show you how lazy you can be, I'll provide a quick tutorial.

  • Install Pshazz with Scoop (scoop install pshazz)
  • Use a nice predefined theme (pshazz use msys)
  • Drink (root) beer

Pshazz also allows you to create your own themes, which is as simple as configuring a JSON file. Check out mine to see how easy it is!

Upvotes: 10

Related Questions