web-dev-qa-db-ja.com

現在のPowerShellスクリプトの場所を特定するための最良の方法は何ですか?

共通のモジュールやスクリプトを参照する必要があるときはいつでも、現在のスクリプトファイルからの相対パスを使用するのが好きです。そうすれば、私のスクリプトは常にライブラリ内の他のスクリプトを見つけることができます。

それでは、現在のスクリプトのディレクトリを決定するための最良の標準的な方法は何ですか?現在、やっています:

$MyDir = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition)

私はモジュール(.psm1)でこの情報を得るために$PSScriptRootを使うことができることを知っていますが、それは通常のスクリプト(すなわち.ps1ファイル)では設定されません。

現在のPowerShellスクリプトファイルの場所を取得するための標準的な方法は何ですか?

450
Aaron Jensen

PowerShell 3+

# This is an automatic variable set to the current file's/module's directory
$PSScriptRoot

PowerShell 2

PowerShell 3より前のバージョンでは、一般的なスクリプトに対してMyInvocation.MyCommand.Definitionプロパティを照会するよりも良い方法はありませんでした。私が持っていた基本的にすべてのPowerShellスクリプトの先頭に次の行がありました。

$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
731
JaredPar

V2モジュールを作成している場合は、$PSScriptRootという自動変数を使用できます。

PSから>ヘルプautomatic_variable

 $ PSScriptRoot 
スクリプトモジュールが実行されているディレクトリを含みます。
この変数は、スクリプトがモジュールパスを使って他の
リソースにアクセスすることを可能にします。 ____。]
57
Andy Schneider

PowerShell 3.0の場合

$PSCommandPath
    Contains the full path and file name of the script that is being run. 
    This variable is valid in all scripts.

機能は次のとおりです。

function Get-ScriptDirectory {
    Split-Path -Parent $PSCommandPath
}
29
CodeMonkeyKing

たぶん私はここに何かが足りないかもしれません...しかし、あなたが現在の作業ディレクトリが欲しいならあなたはただこれを使うことができます:文字列のための(Get-Location).Path、またはオブジェクトのためのGet-Location

このようなことに言及しているのでない限り、質問をもう一度読んだ後に理解します。

function Get-Script-Directory
{
    $scriptInvocation = (Get-Variable MyInvocation -Scope 1).Value
    return Split-Path $scriptInvocation.MyCommand.Path
}
14
Sean C.

Powershell 3+用

function Get-ScriptDirectory {
    if ($psise) {Split-Path $psise.CurrentFile.FullPath}
    else {$global:PSScriptRoot}
}

私は自分のプロファイルにこの機能を追加しました。 ISEでF8/Run Selectionも使用できます。

11
nickkzl

自動変数 $ ExecutionContextを使います。PowerShell2以降で動作します。

$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath('.\')

$ ExecutionContext Windows PowerShellホストの実行コンテキストを表すEngineIntrinsicsオブジェクトが含まれています。この変数を使用して、コマンドレットで使用可能な実行オブジェクトを見つけることができます。

10
Viggos

すでに投稿されている回答と非常によく似ていますが、配管はよりPSに似ているようです。

$PSCommandPath | Split-Path -Parent
10
CPAR

スクリプト名とその実行元を知る必要がありました。

MyInvocation構造体の先頭に "$ global:"を付けると、メインスクリプトとインポートされたPSM1ライブラリファイルのメイン行の両方から呼び出されたときに、フルパスとスクリプト名が返されます。インポートされたライブラリの関数内からも機能します。

いろんなことをやっていたので、私は$ global:MyInvocation.InvocationNameを使うことにしました。 CMDの起動、Run With Powershell、およびISEと確実に連携します。ローカルとUNCの両方の起動で正しいパスが返されます。

7
Bruce Gavin

受け入れられた答えを取り、それを頑健な機能に変える何かを開発するためにしばらく時間がかかりました。

他人についてはわかりませんが、私はPowerShellバージョン2と3の両方のマシンがある環境で作業しているので、両方を処理する必要がありました。次の関数は適切なフォールバックを提供します。

Function Get-PSScriptRoot
{
    $ScriptRoot = ""

    Try
    {
        $ScriptRoot = Get-Variable -Name PSScriptRoot -ValueOnly -ErrorAction Stop
    }
    Catch
    {
        $ScriptRoot = Split-Path $script:MyInvocation.MyCommand.Path
    }

    Write-Output $ScriptRoot
}

また、Michael Sorensが彼の blog で概説したように、関数が親のスコープではなくScriptスコープを参照することも意味します。

7
Bruno

私はいつもPowershellとUSEに同じように働くこの小さな断片を使います:

# set active path to script-location:
$path = $MyInvocation.MyCommand.Path
if (!$path) {$path = $psISE.CurrentFile.Fullpath}
if ( $path) {$path = split-path $path -Parent}
set-location $path
3
Peter

他の方法のいずれかが失敗した場合、split-path -parent $psISE.CurrentFile.Fullpathを検討することもできます。特に、ファイルを実行して一連の関数をロードしてからISEシェルでこれらの関数を実行した場合(または実行選択した場合)、上記のGet-Script-Directory関数は機能しません。

2
user2023266

ここに掲載されている古いソリューションは、PowerShell V5では機能しませんでした。私はこれを思い付きました:

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

1
Quantium