Cmdlet की वर्तमान निर्देशिका को कैसे निष्पादित किया जाए


202

यह एक सरल कार्य होना चाहिए, लेकिन मैंने इस दिशा में कई प्रयास किए हैं कि कैसे निर्देशिका को रास्ता दिया जाए जहां निष्पादित cmdlet मिश्रित सफलता के साथ स्थित है। उदाहरण के लिए, जब मैं निष्पादित C:\temp\myscripts\mycmdlet.ps1करता हूं जिस पर एक सेटिंग फ़ाइल होती है, तो C:\temp\myscripts\settings.xmlमैं C:\temp\myscriptsएक चर में स्टोर करने में सक्षम होना चाहता हूं mycmdlet.ps1

यह एक समाधान है जो काम करता है (हालांकि थोड़ा बोझिल):

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

एक अन्य ने इस समाधान का सुझाव दिया जो केवल हमारे परीक्षण वातावरण पर काम करता है:

$settingspath = '.\settings.xml'

मैं बाद के दृष्टिकोण को बहुत पसंद करता हूं और हर बार एक पैरामीटर के रूप में फ़ाइलपथ को पार्स करने के लिए इसे पसंद करता हूं, लेकिन मैं इसे अपने विकास के वातावरण पर काम करने के लिए नहीं प्राप्त कर सकता हूं। मुझे क्या करना चाहिए? क्या इसके साथ कुछ करना है कि कैसे PowerShell कॉन्फ़िगर किया गया है?


11
ध्यान दें कि इस प्रश्न का अस्पष्ट शीर्षक दो स्पष्ट समस्याओं में से एक को हल करने के बिना नीचे दिए गए उत्तरों के परिणामस्वरूप स्पष्ट रूप से बताया गया है: (ए) वर्तमान स्थान (निर्देशिका) या (बी) को कैसे संदर्भित किया जाए ताकि चल रहे स्क्रिप्ट के स्थान का संदर्भ दिया जा सके वह निर्देशिका जिसमें चालू स्क्रिप्ट स्थित है, जो वर्तमान निर्देशिका हो सकती है या नहीं भी हो सकती है)।
mklement0

जवाबों:


143

ऐसा करने का विश्वसनीय तरीका वैसा ही है जैसा आपने दिखाया $MyInvocation.MyCommand.Path

रिश्तेदार पथ का उपयोग $ pwd पर आधारित होगा, PowerShell में, अनुप्रयोग के लिए वर्तमान निर्देशिका या .NET API के लिए वर्तमान कार्यशील निर्देशिका।

PowerShell v3 + :

स्वचालित चर का उपयोग करें $PSScriptRoot


6
क्या आप मुझे समझा सकते हैं कि आपको संपत्ति कैसे मिली? $ MyInvocation.MyCommand | gm सदस्यों की सूची में ऐसी संपत्ति नहीं दिखाती है।
विटालि मार्किटानोव 15

19
क्यों न केवल $ PSScriptRoot का उपयोग करें? अधिक विश्वसनीय लगता है
mBrice1024

@ user2326106 क्या आप $PSScriptRootऔर के बीच अंतर बता सकते हैं $MyInvocation.MyCommand.Path?
duct_tape_coder 20


यह उत्तर अधूरा है।
स्टैकलिट

263

हां, वह काम करना चाहिए। लेकिन अगर आपको पूर्ण मार्ग देखने की आवश्यकता है, तो आपको केवल यही चाहिए:

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

4
धन्यवाद, रिश्तेदार पथों से पूर्ण पथ खोजने के लिए यह एक शानदार तरीका है। जैसे (Get-Item -ath $ myRelativePath -Verbose) .FullName
dlux

इसके लिए शुक्रिया। अन्य उत्तर EXEs के लिए संकलित Powershell लिपियों के लिए काम नहीं कर रहे थे।
Zach अलेक्जेंडर

10
यह गलत है । यह प्रक्रिया की वर्तमान निर्देशिका प्राप्त करता है , जो कहीं भी हो सकता है। उदाहरण के लिए, यदि मेरी कमांड लाइन वर्तमान निर्देशिका है C:\mydir, और मैं कमांड को लागू करता हूं C:\dir1\dir2\dir3\mycmdlet.ps1, तो यह समाधान करेगा C:\mydir, नहीं C:\dir1\dir2\dir3। नई निष्पादन योग्य को लागू करने में वही समस्या है क्योंकि वर्तमान निर्देशिका मूल प्रक्रिया से विरासत में मिली है।
jpmc26

85

सबसे आसान तरीका निम्नलिखित पूर्वनिर्धारित चर का उपयोग करना प्रतीत होता है:

 $PSScriptRoot

about_Automatic_Variablesऔर about_Scriptsदोनों राज्य:

PowerShell 2.0 में, यह चर केवल स्क्रिप्ट मॉड्यूल (.psm1) में मान्य है। PowerShell 3.0 में शुरुआत, यह सभी लिपियों में मान्य है।

मैं इसे इस तरह से उपयोग करता हूं:

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

12
यह संस्करण विशिष्ट है। इसके लिए कम से कम Powershell 3.0 की आवश्यकता होती है।
मार्विन डिकहौस

1
यह वही है जो मुझे स्क्रिप्ट के रूप में उसी स्थान पर एक फ़ाइल को संदर्भित करने की आवश्यकता है - धन्यवाद!
एडम प्रेस्कॉट

यह सबसे अच्छा जवाब है क्योंकि यह आपको ठीक उसी तरह से रास्ता देता है जहां आप पीएस स्क्रिप्ट पेश करते हैं जो मूल रूप से आपके स्क्रिप्ट निष्पादन के लिए मूल है। यह परवाह नहीं करता है कि आपकी वर्तमान कार्यशील निर्देशिका वह कहाँ से है जहाँ से आपने अपनी स्क्रिप्ट मंगवाई है। +1।
आरबीटी

@MarvinDickhaus यही कारण है कि आपकी अधिकांश लिपियों में "सेट-स्ट्रिक्टमोड -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
धन्यवाद! मैंने इस प्रश्न के शीर्षक को गलत समझा, और यह उत्तर वास्तव में वही था जिसकी मुझे तलाश थी। हालाँकि ... यह सवाल का जवाब नहीं है।
रयान द लीच

33

पथ प्राय: अशक्त है। यह फ़ंक्शन सुरक्षित है।

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? नहीं -स्कॉप 0
suiwenfeng

1
गेट-वेरीएबल: स्कोप नंबर '1' सक्रिय स्कोप की संख्या से अधिक है।
suiwenfeng

2
आपके पास यह त्रुटि हो रही है क्योंकि आपके पास कोई पेरेंट स्कोप नहीं है। -स्कोप पैरामीटर को एक निर्धारित दायरे में चर मिलता है। 1 इस मामले में माता-पिता की गुंजाइश है। अधिक जानकारी के लिए यह तकनीकी लेख Get-Variable ( Technet.microsoft.com/en-us/library/hh849899.aspx ) के बारे में देखें
क्रिश्चियन फ्लेम



11

मुझे वन-लाइन समाधान पसंद है :)

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

यह अब तक का सबसे अच्छा समाधान है।
तेमन शिपाही

हां मेरे लिए काम करता है। मेरी pwd मेरी उपयोगकर्ता निर्देशिका है और मैं एक और निर्देशिका में स्क्रिप्ट चला रहा हूं (B) यह देता है (B)
andrew pate


4

Powershell 3 और इसके बाद के संस्करण में आप बस का उपयोग कर सकते हैं

$PSScriptRoot


1

आपको लगता है कि पथ के रूप में '। \' का उपयोग करने का अर्थ है कि यह आमंत्रण पथ है। लेकिन हर समय नहीं। उदाहरण, यदि आप इसका उपयोग किसी स्क्रिप्ट स्क्रिप्टब्लॉक के अंदर करते हैं। किस स्थिति में, यह% प्रोफ़ाइल% \ Documents को इंगित कर सकता है।


1

यह फ़ंक्शन स्क्रिप्ट स्थान के लिए शीघ्र स्थान निर्धारित करेगा, vscode, psise और pwd के बीच scriptpath प्राप्त करने के लिए अलग-अलग तरीके से निपटते हुए:

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 cmdlet का उपयोग करके उपरोक्त पदों के लिए धन्यवाद ।


0

निम्नलिखित IDE में डीबगिंग के दौरान अधिकांश उत्तर काम नहीं करते हैं:

  • PS-ISE (पॉवरशेल ISE)
  • वीएस कोड (विजुअल स्टूडियो कोड)

क्योंकि उन में $PSScriptRootरिक्त है और Resolve-Path .\(और similars) गलत रास्तों में परिणाम देगा।

Freakydinde का उत्तर केवल वही है जो उन स्थितियों को हल करता है, इसलिए मैंने उसे वोट दिया, लेकिन मुझे नहीं लगता Set-Locationकि उस उत्तर में वास्तव में वही है जो वांछित है। इसलिए मैंने तय किया और कोड को थोड़ा स्पष्ट कर दिया:

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

-1

@ क्रैडल के उत्तर पर विस्तार करने के लिए: आप एक बहुउद्देश्यीय फ़ंक्शन भी लिख सकते हैं जो आपको ओपीडी के अनुसार एक ही परिणाम प्राप्त करेगा:

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 (स्वयं, स्क्रिप्ट नहीं) को आमंत्रित किया गया है, जो असंगत परिणामों को जन्म दे सकता है। इसी वजह से मैं इन्वोकर स्क्रिप्ट का इस्तेमाल करता हूं। अंदर एकल आदेश के साथ PowerShell स्क्रिप्ट POWERSHELL:। यह सुनिश्चित करेगा कि पावरशेल वांछित निर्देशिका से मंगाई गई है और इस तरह से बना है.वर्तमान निर्देशिका का प्रतिनिधित्व करते हैं। लेकिन यह केवल तभी काम करता है जब आप बाद में PowerShell कोड में निर्देशिका नहीं बदलते हैं। एक स्क्रिप्ट के मामले में, मैं इनवॉकर स्क्रिप्ट का उपयोग करता हूं जो मेरे द्वारा बताए गए पिछले एक के समान है, सिवाय इसके कि इसमें एक फ़ाइल विकल्प शामिल है POWERSHELL -FILE DRIVE:\PATH\SCRIPT NAME.PS1:। यह सुनिश्चित करता है कि PowerShell को वर्तमान कार्यशील निर्देशिका के अंदर शुरू किया गया है।

बस स्क्रिप्ट पर क्लिक करने पर PowerShell को आपके घर के उपयोगकर्ता निर्देशिका से कोई फर्क नहीं पड़ता जहां स्क्रिप्ट स्थित है। यह वर्तमान कार्यशील निर्देशिका निर्देशिका जहां स्क्रिप्ट स्थित है, के साथ परिणाम है, लेकिन PowerShell मंगलाचरण निर्देशिका जा रहा है C:\USERS\YOUR USER NAME, और .स्थिति के आधार पर इन दो निर्देशिकाओं में से एक को वापस करने के साथ , जो हास्यास्पद है।

लेकिन इस सभी उपद्रव से बचने और चालान की स्क्रिप्ट का उपयोग करने के लिए, आप बस $PWDया तो वर्तमान निर्देशिका का प्रतिनिधित्व $PSSCRIPTROOTकरने के .लिए या इसके बजाय का उपयोग कर सकते हैं मौसम के आधार पर आप वर्तमान कामकाजी निर्देशिका या निर्देशिका का प्रतिनिधित्व करना चाहते हैं जिसमें से स्क्रिप्ट का आह्वान किया गया है। और अगर आप किसी कारण से, दो निर्देशिकाओं में से अन्य को पुनः प्राप्त करना चाहते हैं, जो .वापस आती है, तो आप उपयोग कर सकते हैं $HOME

मुझे व्यक्तिगत रूप से बस अपने ऐप की रूट डायरेक्टरी के अंदर इनवॉकर स्क्रिप्ट है जो मैं PowerShell के साथ विकसित करता हूं जो मेरे मुख्य ऐप स्क्रिप्ट को आमंत्रित करता है, और बस याद रखना कभी भी अपने ऐप के स्रोत कोड के अंदर वर्तमान कार्यशील निर्देशिका को बदलना नहीं है, इसलिए मुझे इस बारे में चिंता करने की ज़रूरत नहीं है, और मैं .वर्तमान निर्देशिका का प्रतिनिधित्व करने के लिए और किसी भी समस्या के बिना अपने अनुप्रयोगों में रिश्तेदार फ़ाइल पते का समर्थन करने के लिए उपयोग कर सकते हैं । यह पॉवरशेल के नए संस्करणों (संस्करण 2 से नया) में काम करना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.