68

I have a PowerShell script located at D:\temp.

When I run this script, I want the current location of the file to be listed. How do I do this?

For example, this code would accomplish it in a DOS batch file; I am trying to convert this to a PowerShell script...

FOR /f "usebackq tokens=*" %%a IN ('%0') DO SET this_cmds_dir=%%~dpa
CD /d "%this_cmds_dir%"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Santhosh
  • 6,547
  • 15
  • 56
  • 63
  • 1
    Just an observation about how you're doing this in "DOS" (which I assume in this century you mean Windows). Wouldn't it be better just to do: CD "%~dp0"? – Jamie Feb 25 '19 at 20:57
  • In a cmd.exe shell it can be done using `CD /D "%~dp0"`. – lit Nov 01 '19 at 18:56

4 Answers4

146

PowerShell 3+

The path of a running scripts is:

$PSCommandPath

Its directory is:

$PSScriptRoot

PowerShell 2

The path of a running scripts is:

$MyInvocation.MyCommand.Path

Its directory is:

$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
Aaron Jensen
  • 25,861
  • 15
  • 82
  • 91
Roman Kuzmin
  • 40,627
  • 11
  • 95
  • 117
  • 2
    Be careful using `$PSSriptRoot`. It that is a predefined variable within a module. – Keith Hill Sep 08 '10 at 13:35
  • @Keith, basically I agree that it’s not a good idea to recommend $PSScriptRoot for everyone. At least it should not be used in production scripts. I have just copy/pasted this from my “personal” script. I use exactly this name because it is convenient: my code uses $PSScriptRoot everywhere: in modules (built-in) and in scripts (fake). – Roman Kuzmin Sep 08 '10 at 14:20
  • What is a potential danger of using this name in scripts? Perhaps the PowerShell team will finally introduce $PSScriptRoot in ordinary scripts, too, and the variable will be, say, read only. Then yes, there will be a problem in my scripts. I will have to remove my assignment of $PSScriptRoot from my code (disadvantage). But the rest of the code should not be updated and it will use this new feature automatically (advantage). – Roman Kuzmin Sep 08 '10 at 14:21
  • 1
    `PowerShell team will finally introduce $PSScriptRoot in ordinary scripts` - that is what I'm hoping for. When I discovered this variable I was really excited - thinking I could replace the $MyInvocation / Split-Path dance but nooo. :-) Folks who would also like to see this should vote: https://connect.microsoft.com/PowerShell/feedback/details/522951/psscriptroot-only-works-with-modules – Keith Hill Sep 08 '10 at 14:32
  • 21
    That happened. If you're on PowerShell 2 and using this trick, make sure you write: `if(!$PSScriptRoot){ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent }` so that it "just works" in PowerShell 3 – Jaykul Feb 08 '13 at 17:07
  • 4
    I believe that Split-Path $script:MyInvocation.MyCommand.Path is generally preferred over Split-Path $MyInvocation.MyCommand.Path -Parent. See this post for more info: http://stackoverflow.com/questions/801967/how-can-i-find-the-source-path-of-an-executing-script – deadlydog Dec 04 '14 at 16:23
  • 11
    Noteworthy: $PSScriptRoot and $PSCommandPath will be blank if typed into the scripting console in PowerShell ISE, or if executing the selected part of a script file only. It works if the entire script is run. – CodeManX Sep 02 '15 at 15:07
  • 1
    It will work from PowelShell ISE, ONLY if you alredy saved the script file to somewhere. – thepirat000 Nov 28 '16 at 21:42
11

Roman Kuzmin answered the question imho. I'll just add that if you import a module (via Import-Module), you can access $PsScriptRoot automatic variable inside the module -- that will tell you where the module is located.

stej
  • 28,745
  • 11
  • 71
  • 104
1

For what it's worth, I found that this works for me on PowerShell V5 in scripts and in PowerShell ISE:

try {
    $scriptPath = $PSScriptRoot
    if (!$scriptPath)
    {
        if ($psISE)
        {
            $scriptPath = Split-Path -Parent -Path $psISE.CurrentFile.FullPath
        } else {
            Write-Host -ForegroundColor Red "Cannot resolve script file's path"
            exit 1
        }
    }
} catch {
    Write-Host -ForegroundColor Red "Caught Exception: $($Error[0].Exception.Message)"
    exit 2
}

Write-Host "Path: $scriptPath"

HTH

P.S. Included full error handling. Adjust to your needs, accordingly.

Quantium
  • 1,779
  • 1
  • 14
  • 14
0

Here is one example:

$ScriptRoot = ($ScriptRoot, "$PSScriptRoot" -ne $null)[0]
import-module $ScriptRoot\modules\sql-provider.psm1
Import-Module $ScriptRoot\modules\AD-lib.psm1 -Force
live-love
  • 48,840
  • 22
  • 240
  • 204