Ilekroć muszę odwoływać się do wspólnego modułu lub skryptu, lubię używać ścieżek względem bieżącego pliku skryptu. W ten sposób mój skrypt może zawsze znajdować inne skrypty w bibliotece.
Jaki jest najlepszy, standardowy sposób określania katalogu bieżącego skryptu? Obecnie robię:
$MyDir = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition)
Wiem, że w modułach (.psm1) możesz użyć $PSScriptRoot
tej informacji, ale nie ustawia się tego w zwykłych skryptach (np. Plikach .ps1).
Jaki jest kanoniczny sposób uzyskania bieżącej lokalizacji pliku skryptu PowerShell?
powershell
powershell-2.0
Aaron Jensen
źródło
źródło
Odpowiedzi:
PowerShell 3+
PowerShell 2
Przed wersją PowerShell 3 nie było lepszego sposobu niż zapytanie o
MyInvocation.MyCommand.Definition
właściwość o ogólne skrypty. Na początku każdego skryptu PowerShell miałem następujący wiersz:źródło
Split-Path
służy tutaj?Split-Path
jest używany z-Parent
parametrem, aby zwrócić bieżący katalog bez nazwy aktualnie wykonywanego skryptu.$PSScriptRoot
jest (Split-Path -Parent
stosowane)$MyInvocation.MyCommand.Path
, ale nie$MyInvocation.MyCommand.Definition
, chociaż w najwyższym zakresie skryptu zachowują się tak samo (jest to jedyne rozsądne miejsce, z którego można zadzwonić w tym celu). Po wywołaniu w bloku funkcji lub skryptu , ten pierwszy zwraca pusty ciąg znaków, podczas gdy drugi zwraca definicję treści funkcji / bloku skryptu jako ciąg (fragment kodu źródłowego PowerShell).Jeśli tworzysz moduł V2, możesz użyć automatycznej zmiennej o nazwie
$PSScriptRoot
.Z PS> Pomoc zmienna_automatyczna
źródło
$PSCommandPath Contains the full path and file name of the script that is being run. This variable is valid in all scripts.
Dla PowerShell 3.0
Funkcja jest wtedy:
źródło
Dla PowerShell 3+
Umieściłem tę funkcję w moim profilu. Działa również w ISE przy użyciu F8/ Run Selection.
źródło
Może coś mi tu brakuje ... ale jeśli chcesz mieć obecny katalog roboczy, możesz po prostu użyć tego:
(Get-Location).Path
dla łańcucha lubGet-Location
obiektu.Chyba że masz na myśli coś takiego, co rozumiem po ponownym przeczytaniu pytania.
źródło
function Get-Script-Directory { $scriptInvocation = (Get-Variable MyInvocation -Scope 1).Value return Split-Path $scriptInvocation.MyCommand.Path } $hello = "hello" Write-Host (Get-Script-Directory) Write-Host $hello
Zapisz to i uruchom z innego katalogu. Pokażesz ścieżkę do skryptu.Bardzo podobny do już opublikowanych odpowiedzi, ale potokowanie wydaje się bardziej przypominać PowerShell:
źródło
Używam zmiennej automatycznej
$ExecutionContext
. Będzie działać z PowerShell 2 i nowszych.źródło
Zajęło mi trochę czasu opracowanie czegoś, co przyjęło zaakceptowaną odpowiedź i przekształciło ją w solidną funkcję.
Nie jestem pewien co do innych, ale pracuję w środowisku z maszynami zarówno w wersji PowerShell 2, jak i 3, więc musiałem obsłużyć oba. Następująca funkcja oferuje płynną rezerwę:
Oznacza to również, że funkcja odnosi się do zakresu skryptu, a nie zakresu rodzica, jak to nakreślił Michael Sorens w jednym ze swoich postów na blogu .
źródło
Musiałem znać nazwę skryptu i miejsce jego wykonywania.
Przedrostek „$ global:” w strukturze MyInvocation zwraca pełną ścieżkę i nazwę skryptu, gdy jest wywoływany zarówno ze skryptu głównego, jak i głównego wiersza importowanego pliku biblioteki .PSM1. Działa również z funkcji w importowanej bibliotece.
Po wielu zabawach postanowiłem użyć $ global: MyInvocation.InvocationName. Działa niezawodnie z uruchomieniem CMD, Run With Powershell i ISE. Zarówno uruchamianie lokalne, jak i UNC zwracają prawidłową ścieżkę.
źródło
ParameterArgumentValidationErrorNullNotAllowed
wyjątek.Zawsze używam tego małego fragmentu, który działa w PowerShell i ISE w ten sam sposób:
źródło
Przekonałem się, że opublikowane tutaj starsze rozwiązania nie działały dla mnie w PowerShell V5. Wymyśliłem to:
źródło
Możesz również rozważyć,
split-path -parent $psISE.CurrentFile.Fullpath
czy którakolwiek z pozostałych metod zawiedzie. W szczególności, jeśli uruchomisz plik, aby załadować wiązkę funkcji, a następnie uruchomisz te funkcje w powłoce ISE (lub jeśli wybierzesz opcję uruchomienia), wygląda na to, żeGet-Script-Directory
powyższa funkcja nie działa.źródło
$PSCommandPath
będzie działał w ISE, dopóki najpierw zapiszesz skrypt i wykonasz cały plik. W przeciwnym razie nie wykonasz skryptu; po prostu „wklejasz” polecenia do powłoki.Wykorzystując fragmenty wszystkich tych odpowiedzi i komentarzy, zestawiłem to dla każdego, kto zobaczy to pytanie w przyszłości. Obejmuje wszystkie sytuacje wymienione w innych odpowiedziach
źródło
źródło