実行中のコマンドレットの現在のディレクトリを取得する方法


202

これは簡単なタスクですが、実行されたコマンドレットが配置されているディレクトリへのパスを取得する方法について、いくつかの試みがありましたが、成功はさまざまです。たとえばC:\temp\myscripts\mycmdlet.ps1、設定ファイルがあるを実行すると、内の変数C:\temp\myscripts\settings.xmlに保存できるようになりC:\temp\myscriptsますmycmdlet.ps1

これは機能する解決策の1つです(ただし、少し面倒です)。

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

別の人は私たちのテスト環境でのみ機能するこのソリューションを提案しました:

$settingspath = '.\settings.xml'

私は後者のアプローチがとても好きで、毎回ファイルパスをパラメーターとして解析する必要があることを好みますが、私の開発環境で機能させることはできません。どうしたらいいですか?PowerShellの構成方法と関係がありますか?


11
この質問のあいまいなタイトルにより、2つの異なる問題のいずれかが明確に示されずに、以下の回答が得られました。(a)現在の場所(ディレクトリ)を参照する方法、または(b)実行中のスクリプトの場所を参照する方法(実行中のスクリプトが配置されているディレクトリ(現在のディレクトリである場合とそうでない場合があります)。
mklement0 2018年

回答:


143

これを行う確実な方法は、あなたが示したとおり$MyInvocation.MyCommand.Pathです。

相対パスの使用は、PowerShellの$ pwd、アプリケーションの現在のディレクトリ、または.NET APIの現在の作業ディレクトリに基づいています。

PowerShell v3 +

自動変数を使用します$PSScriptRoot


6
プロパティPATHの見つけ方を教えてください。$ MyInvocation.MyCommand | gmは、メンバーリストにそのようなプロパティを表示しません。
Vitaliy Markitanov 16

19
$ PSScriptRootを使用しないのはなぜですか?より信頼できるようです
mBrice1024

@ user2326106 $PSScriptRootとの違いを説明できます$MyInvocation.MyCommand.Pathか?
–duct_tape_coder

1
この答えは不完全です。
K-SOの毒性が高まっています。

この答えは不完全です。
stackleit

263

はい、うまくいくはずです。しかし、絶対パスを確認する必要がある場合は、これで十分です。

(Get-Item .).FullName

4
おかげで、これは相対パスから完全なパスを見つけるための優れた方法です。例(Get-Item -Path $ myRelativePath -Verbose).FullName
dlux

これありがとう。EXEにコンパイルされたPowershellスクリプトに対して他の回答が機能しませんでした。
Zach Alexander

10
これは間違いです。これは、プロセスの現在のディレクトリを取得します。これはどこにあってもかまいません。たとえば、コマンドラインの現在のディレクトリがC:\mydirで、コマンドを呼び出すC:\dir1\dir2\dir3\mycmdlet.ps1場合、これはC:\mydirではなくに解決されC:\dir1\dir2\dir3ます。現在のディレクトリは親プロセスから継承されるため、新しい実行可能ファイルを呼び出す場合も同じ問題があります。
jpmc26

85

最も簡単な方法は、次の定義済み変数を使用することです。

 $PSScriptRoot

about_Automatic_Variablesabout_Scripts両方の状態:

PowerShell 2.0では、この変数はスクリプトモジュール(.psm1)でのみ有効です。PowerShell 3.0以降では、すべてのスクリプトで有効です。

私はそれを次のように使用します:

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

12
これはバージョン固有です。これには少なくともPowershell 3.0が必要です。
Marvin Dickhaus、2015

1
これは、スクリプトと同じ場所にあるファイルを参照するために必要なものです。ありがとうございます。
アダムプレスコット

これは、基本的にスクリプト実行のルートであるPSスクリプトが存在するパスを正確に提供するので、最良の答えです。スクリプトを呼び出した場所から現在の作業ディレクトリを気にする必要はありません。+1。
RBTは

@MarvinDickhausこれが、ほとんどのスクリプトで "Set-StrictMode -Version 3.0"を使用する必要がある理由です:)リンクに感謝します!
アレクサンダーシャプキン

44

次のものも使用できます。

(Resolve-Path .\).Path

括弧内の部分はPathInfoオブジェクトを返します。

(PowerShell 2.0以降で使用できます。)


2
これは間違いです。これは、プロセスの現在のディレクトリを取得します。これはどこにあってもかまいません。たとえば、コマンドラインの現在のディレクトリがC:\mydirで、コマンドを呼び出すC:\dir1\dir2\dir3\mycmdlet.ps1場合、これはC:\mydirではなくに解決されC:\dir1\dir2\dir3ます。現在のディレクトリは親プロセスから継承されるため、新しい実行可能ファイルを呼び出す場合も同じ問題があります。
jpmc26

3
ありがとう!この質問のタイトルも誤解しており、この答えはまさに私が探していたものでした。しかし...それは質問に答えません。
Ryan The Leach

33

多くの場合、パスはnullです。この機能はより安全です。

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("\"));
    }
}

1
なぜ-Scope 1?-Scope 0ではない
suiwenfeng

1
Get-Variable:スコープ番号 '1'はアクティブなスコープの数を超えています。
suiwenfeng 2016年

2
親スコープがないため、このエラーが発生します。-Scopeパラメーターは、指定されたスコープ内の変数を取得します。この場合の1は親スコープです。詳細については、Get-Variableに関するこのtechnetの記事(technet.microsoft.com/en-us/library/hh849899.aspx)を参照してください
クリスチャンフレム


17

Get-Location 現在の場所を返します:

$Currentlocation = Get-Location

3
PS C:\ Windows \ system32> C:\ powershell \ checkfile.ps1->これにより、c:\ windows \ system32
nbi



4

Powershell 3以降では、簡単に使用できます

$PSScriptRoot


1

パスとして「。\」を使用することは、それが呼び出しパスであることを意味すると思います。しかし、いつもではありません。例、ジョブのScriptBlock内で使用する場合。その場合、%profile%\ Documentsをポイントする可能性があります。


1

この関数は、プロンプトの場所をスクリプトパスに設定し、vscode、psise、およびpwd間でスクリプトパスを取得するさまざまな方法を処理します。

function Set-CurrentLocation
{
    $currentPath = $PSScriptRoot                                                                                                     # AzureDevOps, Powershell
    if (!$currentPath) { $currentPath = Split-Path $pseditor.GetEditorContext().CurrentFile.Path -ErrorAction SilentlyContinue }     # VSCode
    if (!$currentPath) { $currentPath = Split-Path $psISE.CurrentFile.FullPath -ErrorAction SilentlyContinue }                       # PsISE

    if ($currentPath) { Set-Location $currentPath }
}

0

価値があるのは、単一行のソリューションであるために、以下は私にとって実用的なソリューションです。

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

最後の1はを無視すること/です。

Get-Locationコマンドレットを使用した上記の投稿に感謝します。


0

次のIDEでデバッグする場合、ほとんどの回答は機能しません。

  • PS-ISE(PowerShell ISE)
  • VSコード(Visual Studio Code)

なぜなら、それら$PSScriptRootは空でありResolve-Path .\(そして類似のものも)、不正なパスをもたらすからです。

Freakydindeの答えはそれらの状況を解決する唯一のものなので、私はそれを賛成票を投じましたが、私はSet-Locationその答えの中で本当に望まれていることだとは思いません。だから私はそれを修正し、コードを少し明確にしました:

$directorypath = if ($PSScriptRoot) { $PSScriptRoot } `
    elseif ($psise) { $psise.CurrentFile.FullPath } `
    elseif ($psEditor) { split-path $psEditor.GetEditorContext().CurrentFile.Path }

-1

@Cradleの答えを拡張すると、OPの質問ごとに同じ結果が得られる多目的関数を作成することもできます。

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
    }

}

-1

現在のディレクトリの名前だけが必要な場合は、次のようにすることができます。

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

C:\ Temp \ Location \ MyWorkingDirectory>から作業していると仮定します

出力

MyWorkingDirectory


-1

同様の問題があり、PowerShell(フルエンドユーザーGUIアプリケーション)で記述されたプログラムを作成していて、ディスクからロードする必要のあるファイルとリソースがたくさんあるので、多くの問題を抱えていました。私の経験から、.現在のディレクトリを表すために使用することは信頼できません。現在の作業ディレクトリを表す必要がありますが、多くの場合は表しません。PowerShellはPowerShellが内部で呼び出された場所を保存するよう.です。より正確には、PowerShellを最初に起動すると、デフォルトではホームユーザーディレクトリ内で起動します。これは通常、次のようなユーザーアカウントのディレクトリです。C:\USERS\YOUR USER NAME。その後、PowerShellはディレクトリを、それを呼び出したディレクトリ、または実行中のスクリプトが置かれているディレクトリに変更してから、PowerShellプロンプトを表示するか、スクリプトを実行します。しかし、これはPowerShellアプリ自体が最初にホームユーザーディレクトリ内で起動した後に発生します。

そして.、PowerShellが起動した最初のディレクトリを表します。したがって.、目的のディレクトリからPowerShellを呼び出した場合にのみ、現在のディレクトリを表します。後でPowerShellコードでディレクトリを変更すると、変更が.すべての場合に内部に反映されないように見えます。.現在の作業ディレクトリを表す場合もあれば、PowerShell(それ自体であり、スクリプトではない)が呼び出されたディレクトリを表す場合もあります。これにより、一貫性のない結果が生じる可能性があります。このため、呼び出しスクリプトを使用しています。内部にコマンドが1つあるPowerShellスクリプト: POWERSHELL。これにより、必要なディレクトリからPowerShellが確実に呼び出され、次のようになります。.現在のディレクトリを表します。ただし、後でPowerShellコードでディレクトリを変更しない場合にのみ機能します。スクリプトの場合は、ファイルオプションが含まれていることを除いて、最後に説明したものと同様の呼び出しスクリプトを使用します POWERSHELL -FILE DRIVE:\PATH\SCRIPT NAME.PS1。これにより、PowerShellが現在の作業ディレクトリ内で確実に起動されます。

スクリプトをクリックするだけで、スクリプトの場所に関係なく、ホームユーザーディレクトリからPowerShellが呼び出されます。その結果、現在の作業ディレクトリはスクリプトが配置されているディレクトリですが、PowerShell呼び出しディレクトリはC:\USERS\YOUR USER NAMEであり.、状況に応じてこれら2つのディレクトリのいずれかを返すというのは、おかしいことです。

しかし、この大騒ぎを回避し、呼び出しスクリプトを使用するために、現在の作業ディレクトリまたはスクリプトが呼び出されたディレクトリを表す天候に応じて、現在のディレクトリを表すために、$PWDまたは$PSSCRIPTROOT代わりに単に使用でき.ます。そして、何らかの理由で、2つのディレクトリのうち他のディレクトリを取得したい.場合は、を使用できます$HOME

個人的には、PowerShellで開発したアプリのルートディレクトリ内に、メインアプリスクリプトを呼び出す起動スクリプトがあり、アプリのソースコード内の現在の作業ディレクトリを決して変更しないことを覚えているので、これについて心配する必要はありません。を使用.して、現在のディレクトリを表し、アプリケーションで相対ファイルのアドレス指定を問題なくサポートできます。これは、PowerShellの新しいバージョン(バージョン2より新しい)で動作するはずです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.