বর্তমান পাওয়ারশেল স্ক্রিপ্টের অবস্থান নির্ধারণের সবচেয়ে ভাল উপায় কী?


530

যখনই আমার একটি সাধারণ মডিউল বা স্ক্রিপ্ট উল্লেখ করতে হবে, আমি বর্তমান স্ক্রিপ্ট ফাইলের সাথে সম্পর্কিত পাথগুলি ব্যবহার করতে চাই। এইভাবে, আমার স্ক্রিপ্ট সবসময় গ্রন্থাগারের অন্যান্য স্ক্রিপ্টগুলি খুঁজে পেতে পারে।

সুতরাং, বর্তমান স্ক্রিপ্টের ডিরেক্টরি নির্ধারণের সর্বোত্তম, মানক উপায় কী? বর্তমানে, আমি করছি:

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

আমি মডিউলগুলিতে জানি (.psm1) আপনি $PSScriptRootএই তথ্যটি পেতে ব্যবহার করতে পারেন তবে এটি নিয়মিত স্ক্রিপ্টগুলিতে সেট হয় না (যেমন .ps1 ফাইল)।

বর্তমান পাওয়ারশেল স্ক্রিপ্ট ফাইলটির অবস্থান প্রাপ্তির সাধারণ উপায় কী?


উত্তর:


865

পাওয়ারশেল 3+

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

পাওয়ারশেল 2

পাওয়ারশেল 3 এর আগে MyInvocation.MyCommand.Definitionসাধারণ স্ক্রিপ্টগুলির জন্য সম্পত্তি জিজ্ঞাসা করার চেয়ে ভাল উপায় আর ছিল না । আমার কাছে প্রতিটি পাওয়ারশেল স্ক্রিপ্টের মূলত নীচের লাইনটি ছিল:

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

1
Split-Pathএখানে কি ব্যবহার করে ?
সিএমসিডিগ্র্যাগনকাই

7
Split-Path-Parentবর্তমানে ডিরেক্টরি সম্পাদনকারী স্ক্রিপ্টের নাম ছাড়াই বর্তমান ডিরেক্টরিটি ফেরত দিতে প্যারামিটারের সাহায্যে ব্যবহৃত হয় ।
hjoelr

5
দ্রষ্টব্য: লিনাক্স / ম্যাকোসে পাওয়ারশেল সহ, আপনার স্ক্রিপ্টটিতে পপুলিপি হতে পিএসএসক্রিপ্ট / মাই ইনভোকেশন ইত্যাদির জন্য একটি .ps1 এক্সটেনশন থাকতে হবে। বাগের প্রতিবেদনটি এখানে দেখুন: github.com
ডেভ উড

3
সম্ভাব্য আকর্ষণীয় একপাশে কুইবলস: কাছাকাছি v2- কাছাকাছি $PSScriptRootহয় ( Split-Path -Parentপ্রয়োগ) $MyInvocation.MyCommand.Path, না $MyInvocation.MyCommand.Definitionযদিও স্ক্রিপ্টের শীর্ষ স্তরের স্কোপগুলিতে তারা একই আচরণ করে (যা এই উদ্দেশ্যে ডাকার একমাত্র বুদ্ধিমান জায়গা)। যখন কোনও ফাংশন বা স্ক্রিপ্ট ব্লকের ভিতরে ডাকা হয় , পূর্ববর্তীটি খালি স্ট্রিংটি ফেরত দেয়, তবে পরেরটি ফাংশনটির বডি / স্ক্রিপ্ট ব্লকের সংজ্ঞাটি স্ট্রিং হিসাবে দেয় (পাওয়ারশেল উত্স কোডের একটি অংশ)।
mklement0

62

আপনি যদি ভি 2 মডিউল তৈরি করে থাকেন তবে আপনি একটি স্বয়ংক্রিয় ভেরিয়েবল নামক ব্যবহার করতে পারেন $PSScriptRoot

পিএস থেকে> স্বয়ংক্রিয়ভাবে পরিবর্তনযোগ্য সহায়তা করুন

$ PSScriptRoot
       স্ক্রিপ্ট মডিউলটি কার্যকর করা হচ্ছে এমন ডিরেক্টরি রয়েছে।
       এই পরিবর্তনশীলটি স্ক্রিপ্টগুলিকে অন্য অ্যাক্সেসের জন্য মডিউল পথ ব্যবহার করতে দেয়
       সম্পদ।

16
পিএস 3.0 এ এটি আপনার প্রয়োজন:$PSCommandPath Contains the full path and file name of the script that is being run. This variable is valid in all scripts.
কোডমনিকিিং

2
সবেমাত্র পরীক্ষিত $ পিএসএস স্ক্রিপ্ট রুট এবং প্রত্যাশার মতো কাজ করা। তবে আপনি যদি কমান্ড লাইনে এটি চালান তবে এটি আপনাকে একটি খালি স্ট্রিং দেয়। কোনও স্ক্রিপ্ট এবং স্ক্রিপ্ট ব্যবহার করা হলে এটি আপনাকে ফলাফল দেয়। এটি এর জন্যই বোঝানো হয়েছে .....
ফররুখ ওয়াহিদ

4
আমি বিভ্রান্ত এই উত্তরটি ভি 2 এর জন্য পিএসএস স্ক্রিপ্ট রুট ব্যবহার করতে বলে। আরেকটি উত্তর বলছে পিএসএস স্ক্রিপ্ট রুটটি ভি 3 + এর জন্য এবং ভি 2 এর জন্য আলাদা কিছু ব্যবহার করার জন্য।

5
@user $ v2 মধ্যে PSScriptRoot শুধুমাত্র জন্য মডিউল , তুমি লেখা 'স্বাভাবিক' স্ক্রিপ্ট নয় মডিউলে আপনি $ MyInvocation.MyCommand.Definition প্রয়োজন হলে, শীর্ষ উত্তর দেখুন।
yzorg

1
@ প্রফুল্ল আমি "ভি 2" তে বলেছিলাম এটি কেবল মডিউলগুলির জন্য সংজ্ঞায়িত হয়েছিল। আপনি বলছেন এটি v3-র মডিউলগুলির বাইরে সংজ্ঞায়িত। আমি মনে করি আমরা একই কথা বলছি। :)
yzorg

35

পাওয়ারশেল 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
}

20
আরও ভাল, $ পিএসএস স্ক্রিপ্ট রুট ব্যবহার করুন। এটি বর্তমান ফাইলের / মডিউলটির ডিরেক্টরি।
অ্যারন জেনসেন

2
এই কমান্ডটিতে স্ক্রিপ্টের ফাইলের নাম অন্তর্ভুক্ত রয়েছে, যা আমি বুঝতে না পারলে আমাকে তাড়িয়ে দেয়। আপনি যখন পথটি চাইছেন, আপনি সম্ভবত সেখানে স্ক্রিপ্টের নামটিও চাইবেন না। কমপক্ষে, আপনি এটি চান এমন কোনও কারণ আমি ভাবতে পারি না। SS পিএসএস স্ক্রিপ্ট রুটে ফাইলের নাম অন্তর্ভুক্ত করা হয় না (অন্যান্য উত্তর থেকে ঝকঝকে)।
তবুও অন্যরেন্ডোম ব্যবহারকারীর

SS পিএসএস স্ক্রিপ্ট রুট একটি নিয়মিত পিএস 1 স্ক্রিপ্ট থেকে খালি। $ পিএসকম্যান্ডপথ যদিও কাজ করে। অন্যান্য পোস্টে দেওয়া বিবরণ অনুযায়ী উভয়ের আচরণ আশা করা যায়। ফাইলের নাম ছাড়াই স্ক্রিপ্ট ডিরেক্টরিটি পেতে কেবল [IO.Path] :: getDirectoryName ($ PSCommandPath) ব্যবহার করতে পারেন।
fizzled

19

পাওয়ারশেল 3+ এর জন্য

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

আমি এই ফাংশনটি আমার প্রোফাইলে রেখেছি। এটি আইএসইতে F8/ রান সিলেকশনও ব্যবহার করে কাজ করে ।


16

হতে পারে আমি এখানে কিছু মিস করছি ... তবে আপনি যদি বর্তমান ওয়ার্কিং ডিরেক্টরি চান তবে আপনি কেবল এটি ব্যবহার করতে পারেন: (Get-Location).Pathএকটি স্ট্রিং বা Get-Locationকোনও অবজেক্টের জন্য।

যদি না আপনি এই জাতীয় কিছু উল্লেখ করছেন, যা আমি আবার প্রশ্নটি পড়ার পরে বুঝতে পারি।

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

16
এটি বর্তমান অবস্থানটি পায় যেখানে ব্যবহারকারী স্ক্রিপ্টটি চালাচ্ছেন । স্ক্রিপ্ট ফাইলের অবস্থান নিজেই নয়
অ্যারন জেনসেন

2
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 এটি সংরক্ষণ করুন এবং এটি একটি ভিন্ন ডিরেক্টরি থেকে চালান। আপনি স্ক্রিপ্টের পথ প্রদর্শন করবেন।
শান সি

এটি একটি ভাল ফাংশন, এবং আমার যা প্রয়োজন তা করে তবে আমি কীভাবে এটি ভাগ করব এবং আমার সমস্ত স্ক্রিপ্টগুলিতে এটি ব্যবহার করব? এটি একটি মুরগির এবং ডিমের সমস্যা: আমি আমার বর্তমান অবস্থানটি অনুসন্ধান করতে একটি ফাংশন ব্যবহার করতে চাই তবে ফাংশনটি লোড করার জন্য আমার অবস্থান প্রয়োজন।
অ্যারন জেনসেন

2
দ্রষ্টব্য: এই ফাংশনটির অনুরোধটি আপনার স্ক্রিপ্টের শীর্ষ স্তরে থাকতে হবে, যদি এটি অন্য ফাংশনের মধ্যে বাসা বাঁধে, তবে আপনি কল স্ট্যাকের মধ্যে কত গভীর তা নির্ধারণ করতে আপনাকে "-স্কোপ" পরামিতিটি পরিবর্তন করতে হবে।
কেনে

11

ইতিমধ্যে পোস্ট করা উত্তরগুলির সাথে খুব সমান, তবে পাইপিং আরও পাওয়ারশেলের মতো বলে মনে হচ্ছে:

$PSCommandPath | Split-Path -Parent

11

আমি স্বয়ংক্রিয় পরিবর্তনশীল ব্যবহার করি $ExecutionContext। এটি পাওয়ারশেল 2 এবং পরে থেকে কাজ করবে।

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

$ এক্সিকিউশন কনটেক্সট এমন একটি ইঞ্জিনআইন্ট্রিনিক্স অবজেক্ট ধারণ করে যা উইন্ডোজ পাওয়ারশেল হোস্টের প্রয়োগের প্রসঙ্গটি উপস্থাপন করে। আপনি এই পরিবর্তনশীলটি সেমিডলেটগুলিতে উপলব্ধ এক্সিকিউশন অবজেক্টগুলি সন্ধান করতে পারেন।


1
এটিই আমার জন্য কাজ করেছে, এসটিডিএন থেকে পাওয়ারশেল খাওয়ানোর চেষ্টা করছে।
সেবাস্তিয়ান

আপনি যখন কোনও ইউএনসি পথের প্রসঙ্গে থাকবেন তখন এই সমাধানটিও সঠিকভাবে কাজ করে।
ব্যবহারকারী 2030503

1
এটি দৃশ্যত ওয়ার্কিং ডিরেক্টরিটি তুলছে - স্ক্রিপ্টটি কোথায় অবস্থিত?
monojohnny

@ মোমোজনহ্নি হ্যাঁ এটি মূলত বর্তমান ওয়ার্কিং ডিরেক্টরি এবং অন্য কোনও স্থান থেকে স্ক্রিপ্ট কল করার সময় কাজ করবে না।
মার্জ করুন

9

এমন কিছু বিকাশ করতে আমার কিছুটা সময় লেগেছিল যা গ্রহণযোগ্য উত্তর নিয়েছিল এবং এটিকে একটি শক্তিশালী ফাংশনে পরিণত করেছে।

আমি অন্যদের সম্পর্কে নিশ্চিত নই, তবে আমি পাওয়ারশেলের সংস্করণ 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
}

এর অর্থ হ'ল এই ফাংশনটি মাইকেল সোরেন্স তার ব্লগ পোস্টগুলির মধ্যে উল্লিখিত মাতাপিতার সুযোগের চেয়ে স্ক্রিপ্টের স্কোপকে বোঝায় ।


ধন্যবাদ! "পাওয়ার স্কেল:" উইন্ডোজ পাওয়ারশেল আইএসইতে এটির কাজ করার জন্য আমার যা প্রয়োজন তা ছিল।
কર્ક লিমোহন

এর জন্য ধন্যবাদ. এই শুধুমাত্র আমার জন্য কাজ করে। আমার জন্য গেট-লোকেশন কাজের মতো জিনিসের আগে স্ক্রিপ্টটি যে ডিরেক্টরিতে থাকে সেটিতে সাধারণত আমার সিডি করতে হয়। পাওয়ারশেল কেন স্বয়ংক্রিয়ভাবে ডিরেক্টরিটি আপডেট করে না তা জানতে আগ্রহী।
জেইন

7

আমার স্ক্রিপ্টের নাম এবং এটি কোথা থেকে কার্যকর হচ্ছে তা জানতে হবে।

মাইআইভোকেশন কাঠামোতে "ix গ্লোবাল:" উপসর্গ তৈরি করা হলে মূল স্ক্রিপ্ট এবং আমদানীকৃত .PSM1 লাইব্রেরী ফাইলের মূল লাইন উভয়কেই ডাকলে পুরো পথ এবং স্ক্রিপ্টের নাম ফিরে আসে। এটি আমদানি করা লাইব্রেরির কোনও ফাংশনের মধ্যে থেকেও কাজ করে।

চারপাশে প্রচুর পরিমাণে ঝাঁকুনির পরে, আমি $ গ্লোবাল: মাই ইনভোকেশন I ইনভোকেশন নাম ব্যবহার করে স্থির হয়েছি। এটি সিএমডি লঞ্চ, রান উইথ পাওয়ারশেল এবং আইএসইয়ের সাথে নির্ভরযোগ্যভাবে কাজ করে। স্থানীয় এবং ইউএনসি উভয়ই সঠিক পথে ফিরে আসে।


4
স্প্লিট-পাথ -পথ $ ($ বিশ্বব্যাপী: মাই ইনভোকেশন.মাইকম্যান্ড.পথ) নিখুঁত ধন্যবাদ কাজ করেছে। অন্যান্য সমাধানগুলি কলিং অ্যাপ্লিকেশনটির পথে ফিরে আসল।
ডায়নামিকালিঙ্ক

1
তুচ্ছ নোট: ISE এ F8 / রান নির্বাচন ব্যবহার করে এই ফাংশনটি কল করা একটি ParameterArgumentValidationErrorNullNotAllowedব্যতিক্রম ট্রিগার করবে ।
ওয়ার

5

আমি সর্বদা এই ছোট স্নিপেটটি ব্যবহার করি যা পাওয়ারশেল এবং আইএসই একইভাবে কাজ করে:

# 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

আমি দেখতে পেয়েছি যে এখানে পোস্ট করা পুরানো সমাধানগুলি পাওয়ারশেল ভি 5 তে আমার পক্ষে কাজ করে না। আমি এটি নিয়ে এসেছি:

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"

2

split-path -parent $psISE.CurrentFile.Fullpathঅন্যান্য পদ্ধতিগুলির মধ্যে কোনওটি ব্যর্থ হয় কিনা তাও আপনি বিবেচনা করতে পারেন। বিশেষত, যদি আপনি গুচ্ছ ফাংশনগুলি লোড করতে কোনও ফাইল চালনা করেন এবং তারপরে আইএসই শেল (বা আপনি যদি নির্বাচিত হন) এর সাহায্যে সেই Get-Script-Directoryফাংশনগুলি সম্পাদন করেন তবে মনে হয় উপরের মতো ফাংশনটি কাজ করে না।


3
$PSCommandPathযতক্ষণ আপনি প্রথমে স্ক্রিপ্টটি সংরক্ষণ করেন এবং পুরো ফাইলটি কার্যকর করেন ততক্ষণ ISE তে কাজ করবে। অন্যথায়, আপনি আসলে কোনও স্ক্রিপ্ট সম্পাদন করছেন না; শেলটিতে আপনি কেবল "আটকানো" কমান্ড।
জেনেক্সার

@ জেনেক্সার আমার মনে হয় সেসময় এটি আমার লক্ষ্য ছিল। যদিও আমার লক্ষ্যটি মূলটির সাথে মেলে না, তবে এটি মাঝে মাঝে Googlers ব্যতীত খুব বেশি সহায়ক নাও হতে পারে ...

2

এই সমস্ত উত্তর এবং মন্তব্যগুলির টুকরোগুলি ব্যবহার করে, আমি ভবিষ্যতে এই প্রশ্নটি যে কেউ দেখতে পাবে তার জন্য এটি একসাথে রেখেছি। এটি অন্যান্য উত্তরে তালিকাভুক্ত সমস্ত পরিস্থিতি কভার করে

    # If using ISE
    if ($psISE) {
        $ScriptPath = Split-Path -Parent $psISE.CurrentFile.FullPath
    # If Using PowerShell 3 or greater
    } elseif($PSVersionTable.PSVersion.Major -gt 3) {
        $ScriptPath = $PSScriptRoot
    # If using PowerShell 2 or lower
    } else {
        $ScriptPath = split-path -parent $MyInvocation.MyCommand.Path
    }

-4
function func1() 
{
   $inv = (Get-Variable MyInvocation -Scope 1).Value
   #$inv.MyCommand | Format-List *   
   $Path1 = Split-Path $inv.scriptname
   Write-Host $Path1
}

function Main()
{
    func1
}

Main
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.