Question

This should be a simple task, but I have seen several attempts on how to get the path to the directory where the executed cmdlet is located with mixed success. For instance, when I execute C:\temp\myscripts\mycmdlet.ps1 which has a settings file at C:\temp\myscripts\settings.xml I would like to be able to store C:\temp\myscripts in a variable within mycmdlet.ps1.

This is one solution which works (although a bit cumbersome):

$invocation = (Get-Variable MyInvocation).Value
$directorypath = Split-Path $invocation.MyCommand.Path
$settingspath = $directorypath + '\settings.xml'

Another one suggested this solution which only works on our test environment:

$settingspath = '.\settings.xml'

I like the latter approach a lot and prefer it to having to parse the filepath as a parameter each time, but I can't get it to work on my development environment. What should I to do? Does it have something to do with how PowerShell is configured?

Was it helpful?

Solution

The reliable way to do this is just like you showed $MyInvocation.MyCommand.Path.

Using relative paths will be based on $pwd, in PowerShell, the current directory for an application, or the current working directory for a .NET API.

PowerShell v3+:

Use the automatic variable $PSScriptRoot.

OTHER TIPS

Yes, that should work. But if you need to see the absolute path, this is all you need:

(Get-Item -Path ".\").FullName

The easiest method seems to be to use the following predefined variable:

 $PSScriptRoot

about_Automatic_Variables and about_Scripts both state:

In PowerShell 2.0, this variable is valid only in script modules (.psm1). Beginning in PowerShell 3.0, it is valid in all scripts.

I use it like this:

 $MyFileName = "data.txt"
 $filebase = Join-Path $PSScriptRoot $MyFileName

You can also use:

(Resolve-Path .\).Path

The part in brackets returns a PathInfo object.

(Available since PowerShell 2.0.)

Path is often null. This function is safer.

function Get-ScriptDirectory
{
    $Invocation = (Get-Variable MyInvocation -Scope 1).Value;
    if($Invocation.PSScriptRoot)
    {
        $Invocation.PSScriptRoot;
    }
    Elseif($Invocation.MyCommand.Path)
    {
        Split-Path $Invocation.MyCommand.Path
    }
    else
    {
        $Invocation.InvocationName.Substring(0,$Invocation.InvocationName.LastIndexOf("\"));
    }
}

Try :

(Get-Location).path

or:

($pwd).path

Get-Location will return the current location:

$Currentlocation = Get-Location

I like the one-line solution :)

$scriptDir = Split-Path -Path $MyInvocation.MyCommand.Definition -Parent

Try this:

$WorkingDir = Convert-Path .

In Powershell 3 and above you can simply use

$PSScriptRoot

You would think that using '.\' as the path means that it's the invocation path. But not all the time. Example, if you use it inside a job ScriptBlock. In which case, it might point to %profile%\Documents.

For what it's worth, to be a single-line solution, the below is a working solution for me.

$currFolderName = (Get-Location).Path.Substring((Get-Location).Path.LastIndexOf("\")+1)

The 1 at the end is to ignore the /.

Thanks to the posts above using the Get-Location cmdlet.

To expand on @Cradle 's answer: you could also write a multi-purpose function that will get you the same result per the OP's question:

Function Get-AbsolutePath {

    [CmdletBinding()]
    Param(
        [parameter(
            Mandatory=$false,
            ValueFromPipeline=$true
        )]
        [String]$relativePath=".\"
    )

    if (Test-Path -Path $relativePath) {
        return (Get-Item -Path $relativePath).FullName -replace "\\$", ""
    } else {
        Write-Error -Message "'$relativePath' is not a valid path" -ErrorId 1 -ErrorAction Stop
    }

}

If you just need the name of the current directory, you could do something like this:

((Get-Location) | Get-Item).Name

Assuming you are working from C:\Temp\Location\MyWorkingDirectory>

Output

MyWorkingDirectory

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top