Search code examples
powershellpathworking-directory

Can I get the current console filepath from which a script was invoked from within said script?


If I am in the console/terminal at the C:\temp location, and I invoke the script C:\scripts\test.ps1, how can I get the path of the current folder (C:\temp) from inside the script I just invoked?

None of the following has the required information:

  • Get-Location
  • $myinvocation
  • $pwd
  • $PSScriptRoot

Solution

  • Note:

    • The next section discusses PowerShell's notion of what the current (working) directory is, which is specific to PowerShell.

      • $pwd and Get-Location typically work - but not always: see below.
    • By contrast, if you want to know what the current process sees as its current directory, which notably applies to calls to .NET APIs, use [Environment]::CurrentDirectory - this is typically not what PowerShell sees as its current location.

      • The reason for this discrepancy, which is rooted in PowerShell's ability to host multiple runspaces (threads) in a single process, is explained in GitHub issue #3428

        • Therefore, robustly calling .NET APIs (in-process) currently requires passing full, native file-system paths - see this answer

        • However, calls to external programs are not affected, because PowerShell does set its notion of the current file-system directory as the working directory of the child process that is invariably created for external programs.

      • Follow-up GitHub issue #17149 ponders synchronizing PowerShell's current (file-system) location with that of the process for the foreground runspace, specifically in the future, starting with an experimental feature; the latter has not yet been implemented as of PowerShell (Core) 7.3.6


    PowerShell's current location vs. its current directory, PowerShell-specific vs. native file-system paths:

    tl;dr

    • $PWD (equivalent to calling Get-Location without arguments) will typically - but not necessarily - reflect PowerShell's current file-system location (working directory).

      • The fully robust solution for returning a string that expresses the working directory as file-system-native path is:

        (Get-Location -PSProvider FileSystem).ProviderPath
        
    • With use of $PWD / argument-less Get-Location, additional considerations apply with respect to (a) whether the resulting object even represents a file-system location, and (b) even if so, whether its form is understood by external programs.

    Read on for background information.


    Get-Location reports PowerShell's current location, which, however, isn't guaranteed to be a file-system location, given that a PowerShell provider other than the FileSystem provider could be the one underlying the current location - even though that is rare in practice.

    Therefore, to robustly determine the full path of the current file-system location, use the following:

    (Get-Location -PSProvider FileSystem).Path
    

    Note that the above expresses the file-system location potentially in terms of PowerShell-only drives, namely if the path passed to Set-Location was expressed in terms of a drive created with New-PSDrive.

    Therefore, to robustly determine the full path of the current file-system location as a native file-system path, use .ProviderPath instead of .Path:

    # .ProviderPath only differs from .Path if the current
    # file-system location is on a PowerShell-only drive
    # (a non-persistent drive established with New-PSDrive)
    (Get-Location -PSProvider FileSystem).ProviderPath
    

    In the simplest case - if you're willing to assume that the current location is a file-system location - you can use the automatic $PWD variable, which is in effect a more efficient alternative to calling Get-Location without arguments.

    # Same as: (Get-Location).Path
    $PWD.Path  # same as: "$PWD" (stringified)
    

    Note:

    • Stringifying a System.Management.Automation.PathInfo instance - as reported by $PWD / Get-Location - results in the value of its .Path property, so situationally you may not need to access the .Path property explicitly; e.g., "The current location is: $PWD"

    • As noted, the .ProviderPath (e.g. $PWD.ProviderPath) returns the native file-system path (for instances representing the paths to items of the FileSystem provider; more generally, it returns the form of the path that is native to the underlying provider).