फ़ाइल पथ में दो से अधिक तार मिलाने के लिए मैं Join-Path का उपयोग कैसे करूं?


105

अगर मैं दो स्ट्रिंग्स को एक फ़ाइल पथ में संयोजित करना चाहता हूं, तो मैं Join-Pathइस तरह का उपयोग करता हूं :

$path = Join-Path C: "Program Files"
Write-Host $path

वह प्रिंट करता है "C:\Program Files"। अगर मैं दो से अधिक तारों के लिए ऐसा करना चाहता हूं, हालांकि:

$path = Join-Path C: "Program Files" "Microsoft Office"
Write-Host $path

PowerShell एक त्रुटि फेंकता है:

ज्वाइन-पाथ: एक स्थितिगत पैरामीटर नहीं पाया जा सकता है जो 'Microsoft Office' के तर्क को स्वीकार करता है।
D: \ users \ ma \ my_script.ps1: 1 char: 18
+ $ path = join-path <<<< C: "प्रोग्राम फाइल्स" "Microsoft Office"
+ श्रेणीइन्फो: अमान्य अमान्य: (:) [Join-Path] , ParameterBindingException
+ FullQualifiedErrorId: PositionalParameterNotFound, Microsoft.PowerShell
.Commands.JoinPathCommand

मैंने एक स्ट्रिंग सरणी का उपयोग करने की कोशिश की:

[string[]] $pieces = "C:", "Program Files", "Microsoft Office"
$path = Join-Path $pieces
Write-Host $path

लेकिन PowerShell ने मुझे चाइल्डपैथ में प्रवेश करने का संकेत दिया (क्योंकि मैंने -childpathतर्क निर्दिष्ट नहीं किया ), जैसे "somepath", और फिर तीन फ़ाइल पथ बनाता है,

C:\somepath
Program Files\somepath
Microsoft Office\somepath

जो सही भी नहीं है।

जवाबों:


171

आप .NET पाथ क्लास का उपयोग कर सकते हैं :

[IO.Path]::Combine('C:\', 'Foo', 'Bar')

3
निश्चित रूप से सबसे संक्षिप्त रूप, और पथ के टुकड़े पर पथ विभाजक और अनुगामी / अग्रणी स्लैश को ठीक से संभालता है, जो वर्तमान स्वीकृत उत्तर (मूल स्ट्रिंग समाकलन) नहीं करता है।
डेविड कीवेनी

3
मेरे अधिकार में ऊपर से निष्पादित करने के लिए यह त्रुटि हो रही है -नोट "गठबंधन" और तर्क गणना के लिए एक अधिभार नहीं मिल रहा है: "3"। लाइन में: 1 char: 19 + [io.path] :: संयोजन <<<< ('c: \', 'foo', 'bar') + CategoryInfo: NotSpecified: (:) [], मेथडसेप्शन + पूरी तरह से एकीकृत ErrorId: MethodCountCouldNotFindBest
Aamol

@ अमोल क्या सीएलआर संस्करण आप चला रहे हैं ( $PSVersionTable)? [io.path]::combine([string[]]('c:\','foo','bar'))काम करता है ?
मर्क टोमन

1
लगता है कि पैरामीटर सीमा 3 है, 3 के बाद पहले पैरामीटर को अनदेखा किया जाता है। (यहाँ कम से कम, ps 5.1, clr 4.0)
एहिलर

4
@DavidKeaveny "पथ अंशों पर पथ विभाजक और अनुगामी / अग्रणी स्लैश को ठीक से संभालता है" - वास्तव में नहीं। join-pathजब भी आपको उम्मीद होती है कि join-path "C:\" "\foo"आउटपुट C:\foo, Path.Combineपहले तर्क की अनदेखी करता है, जब भी दूसरे तर्क में एक अग्रणी विभाजक होता है: [io.path]::combine('c:\', '\foo')कष्टप्रद आउटपुट \foo
क्वांटिक

99

चूंकि Join-Path को एक पथ मान दिया जा सकता है, आप कई Join-Path स्टेटमेंट्स को एक साथ पाइप कर सकते हैं:

Join-Path "C:" -ChildPath "Windows" | Join-Path -ChildPath "system32" | Join-Path -ChildPath "drivers"

यह उतना कठिन नहीं है जितना कि आप शायद इसे पसंद करेंगे, लेकिन यह पूरी तरह से पॉवरशेल है और पढ़ने में अपेक्षाकृत आसान है।


3
+1 चूंकि यह सभी पॉवरशेल 2,3,4 में काम करेगा, इस समस्या के साथ [io.path] :: कॉम्बिने एपीआई अपने अलग .net फ्रेमवर्क 3,4 के लिए अलग है
Ram

18

PowerShell 6.0 के बाद से, शामिल हों-पथ एक है नया पैरामीटर कहा जाता है -AdditionalChildPathऔर कर सकते हैं एक रास्ता बाहर के बॉक्स के कई भागों गठबंधन । या तो अतिरिक्त पैरामीटर प्रदान करके या केवल तत्वों की सूची की आपूर्ति करके।

प्रलेखन से उदाहरण :

Join-Path a b c d e f g
a\b\c\d\e\f\g

तो PowerShell 6.0 में और अपने वैरिएंट के ऊपर

$path = Join-Path C: "Program Files" "Microsoft Office"

उम्मीद के मुताबिक काम करता है!


17

जॉइन-पाथ वह नहीं है जो आप ढूंढ रहे हैं। इसके कई उपयोग हैं, लेकिन वह नहीं जिसकी आप तलाश कर रहे हैं। जॉइनिंग-पाथ के साथ पार्टी करने का एक उदाहरण :

Join-Path C:\hello,d:\goodbye,e:\hola,f:\adios world
C:\hello\world
d:\goodbye\world
e:\hola\world
f:\adios\world

आप देखते हैं कि यह स्ट्रिंग्स के एक सरणी को स्वीकार करता है, और यह बच्चे के स्ट्रिंग को प्रत्येक पथ बनाने के लिए समेटता है। अपने उदाहरण में, $path = join-path C: "Program Files" "Microsoft Office"। जब आप तीन स्थितीय तर्क पास कर रहे हैं और join-pathकेवल दो को स्वीकार कर रहे हैं तो आपको त्रुटि हो रही है । आप जो खोज रहे हैं वह एक है -join, और मैं इसे गलतफहमी के रूप में देख सकता हूं। इसके बजाय अपने उदाहरण से विचार करें:

"C:","Program Files","Microsoft Office" -join "\"

-Joinवस्तुओं की सरणी लेता है और उन्हें \एक स्ट्रिंग में समेटता है।

C:\Program Files\Microsoft Office

एक निस्तारण में मामूली प्रयास

हां, मैं मानूंगा कि यह उत्तर बेहतर है, लेकिन मेरा अभी भी काम कर सकता है। टिप्पणियों का सुझाव है कि स्लैश के साथ एक समस्या हो सकती है, इसलिए मेरे सहमति दृष्टिकोण के साथ रखने के लिए आप ऐसा कर सकते हैं।

"C:","\\Program Files\","Microsoft Office\" -join "\" -replace "(?!^\\)\\{2,}","\"

इसलिए यदि अतिरिक्त स्लैश के साथ समस्याएं हैं, तो इसे तब तक संभाला जा सकता है जब तक वे स्ट्रिंग की शुरुआत में नहीं होते हैं ( UNC पथ की अनुमति देता है)। [io.path]::combine('c:\', 'foo', '\bar\')उम्मीद के मुताबिक काम नहीं होगा और मेरा हिसाब होगा। दोनों को इनपुट के लिए उचित स्ट्रिंग्स की आवश्यकता होती है क्योंकि आप सभी परिदृश्यों का हिसाब नहीं दे सकते। दोनों दृष्टिकोणों पर विचार करें, लेकिन, हाँ, अन्य उच्च-श्रेणी का उत्तर अधिक कठिन है, और मुझे यह भी नहीं पता था कि यह अस्तित्व में है।

इसके अलावा, यह बताना चाहूंगा कि मेरा जवाब बताता है कि मुख्य समस्या का समाधान करने के लिए सुझाव देने के बारे में ओपी क्या गलत कर रहा था।


2
यह गलत है क्योंकि भले ही पथ में कई लगातार \ _ काम करेंगे, यह बदसूरत है और संभावित रूप से समस्याएं पैदा कर सकता है।
मिखाइल ओर्लोव

@MikhailOrlov क्या आप एक संभावित समस्या का वर्णन कर सकते हैं जैसा कि यह सुझाव दिया जा सकता है कि यह हो सकता है? क्या आपके पास एक और सुझाव है? मैं पूछ रहा हूँ क्योंकि मुझे कोई समस्या नहीं दिख रही है। अगर कुछ गलत है तो मैं इसे संबोधित करना चाहूंगा।
मैट

2
मैं हाल ही में बहुत सारे निम्न गुणवत्ता कोड संभाल रहा हूं, लोग खाली स्ट्रिंग को हटाए बिना String.Split ('\\') के साथ String.Equals और पार्स पथों द्वारा पथ की तुलना करते हैं। मैं परिणामों में अधिक खतरनाक कुछ भी नहीं सोच सकता, ज्यादातर मैं सिर्फ पागल हो रहा हूं। आपके संपादन के लिए धन्यवाद।
मिखाइल ओर्लोव

3
पथ विभाजक को शामिल करना स्पष्ट रूप से क्रॉस-प्लेटफॉर्म पोर्टेबिलिटी के साथ समस्याएं पैदा कर सकता है। जबकि PowerShell वर्तमान में केवल Windows पर चलता है, यह बहुत दूर के भविष्य में नहीं बदलने की संभावना है, और जितनी जल्दी हो सके अच्छी आदतों को विकसित करना एक अच्छा विचार है। यह उल्लेख करने के लिए नहीं कि ये आदतें अन्य भाषाओं में स्थानांतरित हो सकती हैं।
18

10

यदि आप अभी भी .NET 2.0 का उपयोग कर रहे हैं, तो आपके [IO.Path]::Combineपास params string[]अधिभार नहीं होगा जिसे आपको दो से अधिक भागों में शामिल होने की आवश्यकता है, और आपको त्रुटि "कॉम्बिनेशन" और तर्क संख्या: "3" के लिए एक अधिभार नहीं मिल पाएगा

थोड़ा कम सुरुचिपूर्ण है, लेकिन एक शुद्ध PowerShell समाधान मैन्युअल रूप से पथ भागों को एकत्रित करना है:

Join-Path C: (Join-Path  "Program Files" "Microsoft Office")

या

Join-Path  (Join-Path  C: "Program Files") "Microsoft Office"

5

चाइल्डपैथ के लिए एक स्ट्रिंग ऐरे का उपयोग करते समय आप कुछ ऐसा करेंगे जो आप चाहते हैं।

$path = "C:"
@( "Program Files", "Microsoft Office" ) | %{ $path = Join-Path $path $_ }
Write-Host $path

जो आउटपुट देता है

C:\Program Files\Microsoft Office

केवल एक ही चेतावनी मुझे मिली है कि $ पथ के लिए प्रारंभिक मूल्य का मूल्य होना चाहिए (शून्य या रिक्त नहीं हो सकता)।


4

एक मार्ग में घटकों की एक मनमानी संख्या में शामिल होने के लिए शुद्ध पॉवरशेल फ़ंक्शन लिखने के दो और तरीके हैं।

यह पहला फ़ंक्शन सभी घटकों को संग्रहीत करने के लिए एक एकल सरणी का उपयोग करता है और फिर उन्हें संयोजित करने के लिए एक फ़ॉरच लूप:

function Join-Paths {
    Param(
        [Parameter(mandatory)]
        [String[]]
        $Paths
    )
    $output = $Paths[0]
    foreach($path in $Paths[1..$Paths.Count]) {
        $output = Join-Path $output -ChildPath $path
    }
    $output
}

क्योंकि पथ घटक एक सरणी में तत्व हैं और एक ही तर्क के सभी भाग, उन्हें अल्पविराम से अलग किया जाना चाहिए। उपयोग निम्नानुसार है:

PS C: \> Join-Paths 'C:', 'Program Files', 'Microsoft Office'
C: \ Program Files \ Microsoft कार्यालय


इस फ़ंक्शन को लिखने का एक और न्यूनतम तरीका बिल्ट-इन $argsचर का उपयोग करना है , और फिर माइक मेले की विधि का उपयोग करके एक पंक्ति में फोरच लूप को ढहना है।

function Join-Paths2 {
    $path = $args[0]
    $args[1..$args.Count] | %{ $path = Join-Path $path $_ }
    $path
}

फ़ंक्शन के पिछले संस्करण के विपरीत, प्रत्येक पथ घटक एक अलग तर्क है, इसलिए तर्कों को अलग करने के लिए केवल एक स्थान आवश्यक है:

PS C: \> Join-Paths2 'C:' 'Program Files' 'Microsoft Office'
C: \ Program Files \ Microsoft कार्यालय

2

ज्वाइन-पाथ स्टेटमेंट्स की तुलना में निम्नलिखित दृष्टिकोण अधिक संक्षिप्त है:

$p = "a"; "b", "c", "d" | ForEach-Object -Process { $p = Join-Path $p $_ }

$ p उसके बाद संक्षिप्त पथ 'a \ b \ c \ d' रखता है।

(मैंने अभी देखा कि यह माइक फेयर के रूप में ठीक वही दृष्टिकोण है, क्षमा करें।)


1

या आप इसके लिए अपना स्वयं का कार्य लिख सकते हैं (जो कि मैंने करना समाप्त कर दिया है)।

function Join-Path-Recursively($PathParts) {
    $NumberOfPathParts = $PathParts.Length;

    if ($NumberOfPathParts -eq 0) {
        return $null
    } elseif ($NumberOfPathParts -eq 1) {
        return $PathParts[0]
    } else {
        return Join-Path -Path $PathParts[0] -ChildPath $(Join-Path-Recursively -PathParts $PathParts[1..($NumberOfPathParts-1)])
    }
}

फिर आप इस तरह से फ़ंक्शन को कॉल कर सकते हैं:

Join-Path-Recursively -PathParts  @("C:", "Program Files", "Microsoft Office")
Join-Path-Recursively  @("C:", "Program Files", "Microsoft Office")

यह सामान्य Join-Path फ़ंक्शन के समान सटीक व्यवहार करने का लाभ है और .NET Framework पर निर्भर करता है।


0

आप इसे इस तरह से उपयोग कर सकते हैं:

$root = 'C:'
$folder1 = 'Program Files (x86)'
$folder2 = 'Microsoft.NET'

if (-Not(Test-Path $(Join-Path $root -ChildPath $folder1 | Join-Path -ChildPath $folder2)))
{
   "Folder does not exist"
}
else 
{
   "Folder exist"
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.