PowerShell: स्क्रिप्ट की निर्देशिका से कमांड चलाएँ


144

मेरे पास एक PowerShell स्क्रिप्ट है जो स्क्रिप्ट की वर्तमान निर्देशिका का उपयोग करके कुछ सामान करता है। तो जब उस निर्देशिका के अंदर, रनिंग .\script.ps1सही ढंग से काम करता है।

अब मैं स्क्रिप्ट के संदर्भ निर्देशिका को बदले बिना उस स्क्रिप्ट को एक अलग निर्देशिका से कॉल करना चाहता हूं। इसलिए मैं कॉल करना चाहता हूं ..\..\dir\script.ps1और फिर भी वह स्क्रिप्ट व्यवहार करना चाहता हूं जैसा कि इसकी निर्देशिका के अंदर से बुलाया गया था।

मैं ऐसा कैसे करूं, या मैं किसी स्क्रिप्ट को कैसे संशोधित करूं ताकि यह किसी भी निर्देशिका से चल सके?

जवाबों:


200

क्या आपका मतलब है कि आप स्क्रिप्ट का अपना रास्ता चाहते हैं ताकि आप स्क्रिप्ट के बगल में एक फ़ाइल का संदर्भ ले सकें? इसे इस्तेमाल करे:

$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
Write-host "My directory is $dir"

आप $ MyInvocation और इसके गुणों से बहुत सारी जानकारी प्राप्त कर सकते हैं।

यदि आप वर्तमान कार्यशील निर्देशिका में किसी फ़ाइल का संदर्भ लेना चाहते हैं, तो आप रिज़ॉल्व-पाथ या गेट-चाइल्डइम का उपयोग कर सकते हैं:

$filepath = Resolve-Path "somefile.txt"

EDIT (ओपी की टिप्पणी पर आधारित):

# temporarily change to the correct folder
Push-Location $folder

# do stuff, call ant, etc

# now back to previous directory
Pop-Location

इनवोक-कमांड का उपयोग करने के साथ-साथ कुछ समान हासिल करने के अन्य तरीके भी हैं।


1
हम्म, ठीक है, शायद मुझे अपनी स्क्रिप्ट के बारे में थोड़ा और स्पष्ट होना चाहिए था। दरअसल यह एक स्क्रिप्ट है जो antकुछ मापदंडों के साथ कॉल करती है । इसलिए मुझे antयह सुनिश्चित करने के लिए उस फ़ोल्डर से कॉल करना होगा कि यह कॉन्फ़िगरेशन फ़ाइल को सही ढंग से ढूंढता है। आदर्श रूप से मैं उस स्क्रिप्ट के भीतर स्थानीय रूप से निष्पादन निर्देशिका को अस्थायी रूप से बदलने के लिए कुछ ढूंढ रहा हूं।
प्रहार

3
फिर उस स्थिति में आप चाहेंगे Push-LocationऔरPop-Location
JohnL

5
उस के बारे में सावधान, $ MyInvocation है संदर्भ संवेदनशील, मैं आमतौर पर करते हैं $ ScriptPath = (प्राप्त करें-चर MyInvocation -Scope स्क्रिप्ट) .Value.MyCommand.Path जो घोंसले या समारोह के किसी भी प्रकार से काम करता है

39

यदि आप मूल एप्लिकेशन कॉल कर रहे हैं, तो आपको [Environment]::CurrentDirectoryPowerShell की $PWDवर्तमान निर्देशिका के बारे में चिंता करने की आवश्यकता है । विभिन्न कारणों से, जब आप सेट-लोकेशन या पुश-लोकेशन करते हैं, तो पावरशेल प्रक्रिया की वर्तमान वर्किंग डायरेक्टरी को सेट नहीं करता है, इसलिए आपको यह सुनिश्चित करने की आवश्यकता है कि यदि आप एप्लिकेशन (या cmdlets) चला रहे हैं तो यह सेट होने की उम्मीद है।

एक स्क्रिप्ट में, आप यह कर सकते हैं:

$CWD = [Environment]::CurrentDirectory

Push-Location $MyInvocation.MyCommand.Path
[Environment]::CurrentDirectory = $PWD
##  Your script code calling a native executable
Pop-Location

# Consider whether you really want to set it back:
# What if another runspace has set it in-between calls?
[Environment]::CurrentDirectory = $CWD

इसका कोई मूर्खतापूर्ण विकल्प नहीं है। हम में से कई लोग [पर्यावरण] :: CurrentDirectory ... को सेट करने के लिए हमारे प्रॉम्प्ट फ़ंक्शन में एक लाइन डालते हैं ... लेकिन यह तब आपकी मदद नहीं करता है जब आप किसी स्क्रिप्ट के भीतर स्थान बदल रहे होते हैं ।

कारण के बारे में दो नोट क्यों यह PowerShell द्वारा स्वचालित रूप से सेट नहीं किया गया है:

  1. PowerShell को बहु-थ्रेड किया जा सकता है। आपके पास एक एकल प्रक्रिया में एक साथ कई रनस्पेस (रनस्पेसपूल और PSThreadJob मॉड्यूल देखें) हो सकते हैं। प्रत्येक रनस्पेस की अपनी $PWDवर्तमान कार्यशील निर्देशिका है, लेकिन केवल एक प्रक्रिया है, और केवल एक पर्यावरण है।
  2. यहां तक ​​कि जब आप सिंगल-थ्रेडेड होते हैं, $PWDतो हमेशा एक कानूनी करंटडायरेक्टरी (आप उदाहरण के लिए रजिस्ट्री प्रदाता में सीडी कर सकते हैं) नहीं है।

यदि आप इसे अपने प्रॉम्प्ट में डालना चाहते हैं (जो केवल मुख्य रनवे, सिंगल-थ्रेडेड में चलेगा), तो आपको उपयोग करने की आवश्यकता है:

[Environment]::CurrentDirectory = Get-Location -PSProvider FileSystem

4
यह पथ प्रदाताओं की वजह से कार्यशील निर्देशिका को नहीं बदलता है: आप रजिस्ट्री, SQL डेटाबेस या IIS हाइव आदि में
CD'ing हो सकते हैं

1
हाँ। मुझे पता है, यह उस अंतिम "फाइनल नोट" का बिंदु था। वे कर सकते हैं (जैसा कि मैं अपने प्रॉम्प्ट फ़ंक्शन में करता हूं) ने इसे दुनिया के हर दूसरे शेल की तरह, फाइलसिस्टम प्रदाता के वर्तमान स्थान पर अपडेट किया।
Jaykul

2
पवित्र स्क्रिप्टिंग देवता, मैं बहुत निराश हूँ .\_/.- क्योंकि यह मेरे दिन का आधा हिस्सा है! लोग, गंभीरता से? गंभीरता से? ..
ulidtko

2
जब वे बाइनरी ऐप लॉन्च करते हैं, तो यह ज्यादातर आवश्यक नहीं होता है कि पावरशेल के अधिक आधुनिक संस्करण काम करने वाले निर्देशिका को सेट करें।
जयकुल

1
यह विधि मूल को पुनर्स्थापित करने में विफल रहती है [Environment]::CurrentDirectoryजब इससे भिन्न होता है $PWD। सही बात यह है कि इसे एक चर में संग्रहीत किया जाएगा $origEnvDir = [Environment]::CurrentDirectoryऔर फिर बाद में इसे पुनर्स्थापित किया जाएगा [Environment]::CurrentDirectory = $origEnvDir
Strom

37

बड़ी संख्या में वोटों के उत्तर हैं, लेकिन जब मैंने आपका प्रश्न पढ़ा, तो मुझे लगा कि आप उस निर्देशिका को जानना चाहते हैं जहां स्क्रिप्ट है, न कि वह जहां स्क्रिप्ट चल रही है। आप पॉवरशेल के ऑटो चर के साथ जानकारी प्राप्त कर सकते हैं

$PSScriptRoot - the directory where the script exists, not the target directory the script is running in
$PSCommandPath - the full path of the script

उदाहरण के लिए, मेरे पास $ प्रोफ़ाइल स्क्रिप्ट है जो दृश्य स्टूडियो समाधान फ़ाइल ढूंढती है और इसे शुरू करती है। मैं एक संपूर्ण समाधान संग्रहीत करना चाहता था, एक बार जब एक समाधान फ़ाइल शुरू होती है। लेकिन मैं उस फ़ाइल को सहेजना चाहता था जहाँ मूल स्क्रिप्ट मौजूद है। इसलिए मैंने $ PsScriptRoot का उपयोग किया।


12

मैंने अक्सर एक मॉड्यूल आयात करने के लिए निम्न कोड का उपयोग किया था जो चल रहे स्क्रिप्ट के समान निर्देशिका के नीचे बैठते हैं। यह पहले निर्देशिका प्राप्त करेगा जिसमें से शक्तियां चल रही हैं

$ currentPath = स्प्लिट-पाथ ((Get-Variable MyInvocation -Scope 0)। वाल्यू) ।MyCommand.Path।

आयात-मॉड्यूल "$ currentPath \ sqlps.ps1"


आप स्क्रिप्ट पर सेट करना चाहते हैं

9

यह ठीक काम करेगा।

Push-Location $PSScriptRoot

Write-Host CurrentDirectory $CurDir

Pop-Locationअपनी मूल स्थिति पर लौटने के लिए अंत में कॉल करना न भूलें ।
लैम ले

2

वैसे मैं इसके लिए कुछ समय के लिए समाधान की तलाश कर रहा था, बिना किसी स्क्रिप्ट के सिर्फ सीएलआई से। यह है कि मैं इसे कैसे करता हूं:

  • उस फ़ोल्डर पर नेविगेट करें जिससे आप स्क्रिप्ट चलाना चाहते हैं (महत्वपूर्ण बात यह है कि आपके पास टैब पूर्णियां हैं)

    ..\..\dir

  • अब डबल कोट्स के साथ लोकेशन को घेरें, और उनके अंदर ऐड करें cd, ताकि हम पावरशेल के एक और उदाहरण को लागू कर सकें।

    "cd ..\..\dir"

  • स्क्रिप्ट को अलग से चलाने के लिए एक और कमांड जोड़ें ;, जिसमें शक्तियां अलग हैं

    "cd ..\..\dir\; script.ps1"

  • अंत में इसे पॉवरशेल के एक और उदाहरण के साथ चलाएं

    start powershell "cd..\..\dir\; script.ps1"

इससे नई पॉवरशेल विंडो खुल जाएगी, गो टू ..\..\dir, रन script.ps1और क्लोज विंडो।


ध्यान दें कि ";" बस आज्ञाओं को अलग करता है, जैसे कि आपने उन्हें एक-एक करके टाइप किया, अगर पहली बार असफल होता है तो दूसरा चलेगा और उसके बाद, और उसके बाद अगला ... यदि आप नई शक्तियां खोलना चाहते हैं तो आप जोड़-जोड़कर पास कमांड में खोल सकते हैं। ध्यान दें कि मैं पहले वांछित फ़ोल्डर में नेविगेट करता हूं ताकि मैं टैब पूर्णता का उपयोग कर सकूं (आप दोहरे उद्धरणों में नहीं कर सकते)।

start powershell "-noexit cd..\..\dir\; script.ps1"

दोहरे उद्धरण चिह्नों का उपयोग करें ""ताकि आप निर्देशिका को नामों में रिक्त स्थान के साथ पारित कर सकें, जैसे,

start powershell "-noexit cd '..\..\my dir'; script.ps1"


0

मैंने @ जॉनएल के समाधान में से एक-लाइनर बनाया:

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