পাওয়ারশেলে কোনও পাথ কীভাবে সাধারণ করবেন?


96

আমার দুটি পথ রয়েছে:

fred\frog

এবং

..\frag

আমি এগুলির মতো পাওয়ারশেলে তাদের সাথে একসাথে যোগদান করতে পারি:

join-path 'fred\frog' '..\frag'

এটি আমাকে দেয়:

fred\frog\..\frag

তবে আমি তা চাই না। আমি ডাবল ডটগুলি ছাড়াই একটি সাধারণীকরণের পথ চাই:

fred\frag

আমি কীভাবে এটি পেতে পারি?


4
টুকরা কি ব্যাঙের একটি সাবফোল্ডার? যদি না হয় তবে পাথের সংমিশ্রণটি আপনাকে ফ্রেড og ব্যাঙ \ টুকরো টুকরো টুকরো করে দেবে। যদি তা হয় তবে এটি একটি খুব আলাদা প্রশ্ন।
EBGreen

উত্তর:


83

আপনি একটি সমন্বয় ব্যবহার করতে পারেন pwd, Join-Pathএবং [System.IO.Path]::GetFullPathএকটি সম্পূর্ণরূপে যোগ্যতাসম্পন্ন প্রসারিত পথ পেতে।

যেহেতু cd( Set-Location) প্রক্রিয়াটির বর্তমান কার্যনির্বাহী ডিরেক্টরিটি পরিবর্তন করে না, কেবল পাওয়ারশেল প্রসঙ্গটি বোঝে না এমন একটি নেট নেট এপিআই-তে একটি সম্পর্কিত আপেক্ষিক ফাইলের নাম পাস করার ফলে অনিচ্ছাকৃত পার্শ্ব-প্রতিক্রিয়া থাকতে পারে, যেমন প্রাথমিক কাজ বন্ধের ভিত্তিতে কোনও পথে সমাধান করা as ডিরেক্টরি (আপনার বর্তমান অবস্থান নয়)।

আপনি যা করেন তা হ'ল আপনি প্রথমে আপনার পথটিকে যোগ্য করে তোলেন:

Join-Path (Join-Path (pwd) fred\frog) '..\frag'

এই ফলন (আমার বর্তমান অবস্থান দেওয়া):

C:\WINDOWS\system32\fred\frog\..\frag

একটি নিখুঁত বেস সহ, .NET এপিআই কল করা নিরাপদ GetFullPath:

[System.IO.Path]::GetFullPath((Join-Path (Join-Path (pwd) fred\frog) '..\frag'))

যা আপনাকে পুরোপুরি যোগ্য পথ এবং ..সরানো সহ:

C:\WINDOWS\system32\fred\frag

এটি জটিলভাবে হয় না, ব্যক্তিগতভাবে, আমি এর জন্য বাহ্যিক স্ক্রিপ্টগুলির উপর নির্ভরশীল সমাধানগুলি উপেক্ষা করি, এটি সাধারণ সমস্যাটি বরং যথাযথভাবে সমাধান করা হয়েছে Join-Pathএবং pwd( GetFullPathকেবল এটি সুন্দর করার জন্য)। আপনি যদি কেবলমাত্র আপেক্ষিক অংশ রাখতে চান তবে আপনি কেবল যোগ করুন .Substring((pwd).Path.Trim('\').Length + 1)এবং ভয়েলা!

fred\frag

হালনাগাদ

C:\প্রান্তের কেসটি নির্দেশ করার জন্য @ ডাংফকে ধন্যবাদ জানাই ।


Pwd "C: \" হলে শেষ পদক্ষেপটি কাজ করে না doesn't সেক্ষেত্রে আমি "লাল \ টুকরা" পাই।
ড্যান-জিএফ

@ ড্যাংএফ - নিশ্চিত না যে আপনি কী বোঝাতে চেয়েছেন, উপরেরটি ঠিক ঠিক কাজ করছে বলে মনে হচ্ছে? আপনি পাওয়ারশেলের কোন সংস্করণ ব্যবহার করছেন? আমি সংস্করণ 3.0 ব্যবহার করছি।
জন লিডেগ্রেন

4
আমি শেষ পদক্ষেপ বলতে চাই : cd c:\; "C:\fred\frag".Substring((pwd).Path.Length + 1). এটি একটি বড় চুক্তি না; কিছু সচেতন হতে হবে।
ড্যান-জিএফ

আহ, ভাল ক্যাচ, আমরা ট্রিম কল যোগ করে এটি ঠিক করতে পারি could ব্যবহার করে দেখুন cd c:\; "C:\fred\frag".Substring((pwd).Path.Trim('\').Length + 1)। এটি যদিও দীর্ঘ সময় পেয়ে যাচ্ছে।
জন লিডেগ্রেন

4
বা, কেবলমাত্র ব্যবহার করুন: ution এক্সিকিউশনকন্টেক্সট.সেশনস্টেট.পথ.গেট অনারসলডপ্রোভিডারপথফ্রোমপ্যাসপ্যাথ ("" \ noxist \ foo.txt ") অ-অস্তিত্বশীল পাথের সাথেও কাজ করে। "x0n" এই বিটিডব্লিউর জন্য কৃতিত্বের দাবিদার। যেমনটি তিনি লক্ষ করেছেন, এটি পিএসপ্যাথগুলিতে সমাধান হয়েছে, ফ্লাইসিসটেম পাথগুলি নয়, তবে আপনি যদি পাওয়ারশেলের পথগুলি ব্যবহার করেন তবে কে যত্ন করে? stackoverflow.com/questions/3038337/…
জো কোডার

106

আপনি প্রসারণ করতে পারেন .. resolve সমাধান-পথের সাথে এর সম্পূর্ণ পথে ভঙ্গ:

PS > resolve-path ..\frag 

কম্বাইন () পদ্ধতিটি ব্যবহার করে পাথটিকে সাধারণ করার চেষ্টা করুন:

[io.path]::Combine("fred\frog",(resolve-path ..\frag).path)

আপনার পথটি যদি একই পথে C:\Windowsবনাম C:\Windows\ তবে দুটি পৃথক ফলাফল হয়
জো ফিলিপস

4
এর জন্য প্যারামিটারগুলি [io.path]::Combineবিপরীত। আরও ভাল, নেটিভ Join-Pathপাওয়ারশেল কমান্ডটি ব্যবহার করুন : Join-Path (Resolve-Path ..\frag).Path 'fred\frog'এছাড়াও নোট করুন, কমপক্ষে পাওয়ারশেল v3 হিসাবে, Resolve-Pathএখন -Relativeবর্তমান ফোল্ডারের সাথে সম্পর্কিত কোনও পথের সমাধানের জন্য স্যুইচটিকে সমর্থন করে । হিসাবে উল্লেখ করেছে, Resolve-Pathশুধুমাত্র অসদৃশ বিদ্যমান পাথ সাথে কাজ করে [IO.Path]::GetFullPath()
mklement0

25

আপনি পাথ.গেটফুলপাথও ব্যবহার করতে পারেন , যদিও (ড্যান আর এর উত্তর হিসাবে) এটি আপনাকে পুরো পথ দেবে। ব্যবহার নিম্নরূপ হবে:

[IO.Path]::GetFullPath( "fred\frog\..\frag" )

বা আরও আকর্ষণীয়ভাবে

[IO.Path]::GetFullPath( (join-path "fred\frog" "..\frag") )

উভয়ই নিম্নলিখিত উত্পন্ন করে (আপনার বর্তমান ডিরেক্টরিটি ডি: um ধরে ধরে):

D:\fred\frag

দ্রষ্টব্য যে এই পদ্ধতিটি ফ্রেড বা টুকরা আসলে বিদ্যমান কিনা তা নির্ধারণের চেষ্টা করে না।


এটি নিকটবর্তী হচ্ছে, তবে আমি যখন এটি চেষ্টা করি তখন আমার বর্তমান ডিরেক্টরিটি "সি: \ স্ক্র্যাচ" হওয়া সত্ত্বেও "এইচ: red ফ্রেড \ ফ্লেজ" পাই যা ভুল। (এমএসডিএন অনুসারে এটি করা উচিত নয়)) তবে এটি আমাকে একটি ধারণা দিয়েছে। আমি এটিকে উত্তর হিসাবে যুক্ত করব।
ড্যান-জিএফ

8
আপনার সমস্যাটি হ'ল আপনাকে বর্তমান ডিরেক্টরিটি। নেট এ সেট করতে হবে। [System.IO.Directory]::SetCurrentDirectory(((Get-Location -PSProvider FileSystem).ProviderPath))
জেসনমারচার

4
কেবল এটি স্পষ্টভাবে বলতে: [IO.Path]::GetFullPath()পাওয়ারশেলের নেটিভ থেকে ভিন্ন Resolve-Path, অস্তিত্বহীন পাথগুলির সাথেও কাজ করে। এর জবাবটি হ'ল নেট জেনারম্যাচারের পয়েন্ট হিসাবে প্রথমে পিএস'র সাথে নেট নেট ওয়ার্কিং ফোল্ডার সিঙ্ক করা দরকার।
mklement0

Join-Pathঅস্তিত্ব নেই এমন কোনও ড্রাইভের কথা উল্লেখ করে একটি ব্যতিক্রম ঘটায়।
তাহির হাসান

20

গৃহীত উত্তরটি একটি দুর্দান্ত সহায়তা ছিল তবে এটি একটি নিখুঁত পথকে যথাযথভাবে 'সাধারণীকরণ' করে না। আমার ডেরাইভেটিভ কাজের নীচে সন্ধান করুন যা পরম এবং আপেক্ষিক পাথ উভয়ই স্বাভাবিক করে তোলে।

function Get-AbsolutePath ($Path)
{
    # System.IO.Path.Combine has two properties making it necesarry here:
    #   1) correctly deals with situations where $Path (the second term) is an absolute path
    #   2) correctly deals with situations where $Path (the second term) is relative
    # (join-path) commandlet does not have this first property
    $Path = [System.IO.Path]::Combine( ((pwd).Path), ($Path) );

    # this piece strips out any relative path modifiers like '..' and '.'
    $Path = [System.IO.Path]::GetFullPath($Path);

    return $Path;
}

সমস্ত বিভিন্ন সমাধান দেওয়া, এটি এক সমস্ত বিভিন্ন ধরণের পাথের জন্য কাজ করে। উদাহরণ হিসাবে [IO.Path]::GetFullPath()সঠিকভাবে একটি সরল ফাইলের নামের জন্য ডিরেক্টরি নির্ধারণ করে না।
জারি তুর্কিয়া

10

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

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

নিম্নলিখিত খুব সাধারণ সেমিডলেটটি অ অযৌক্তিক পাথের জন্য কাজ করা উচিত। এটি 'ফ্রেড \ ব্যাঙ \ .. \ ফ্লেজ' কে 'ডি: ডি ফ্রেড' ফ্রেমে রূপান্তরিত করবে এমনকি 'ফ্রেড' বা 'ফ্রেজ' ফাইল বা ফোল্ডারটি পাওয়া না গেলেও (এবং বর্তমান পাওয়ারশেল ড্রাইভটি 'ডি:' রয়েছে) ।

function Get-AbsolutePath {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [string[]]
        $Path
    )

    process {
        $Path | ForEach-Object {
            $PSCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath($_)
        }
    }
}

4
এটি অ-অযৌক্তিক পাথের জন্য কাজ করে না যেখানে ড্রাইভ লেটারের অস্তিত্ব নেই যেমন আমার কাছে কোন প্রশ্ন: ড্রাইভ নেই। Get-AbsolutePath q:\foo\bar\..\bazএটি বৈধ পথ হলেও ব্যর্থ হয়। ভাল, আপনার বৈধ পাথের উপর নির্ভর করে। :-) এফডাব্লুআইডাব্লু, এমনকি বিল্ট-ইনগুলি Test-Path <path> -IsValidঅস্তিত্বহীন ড্রাইভে থাকা মূলগুলিতে ব্যর্থ হয়।
কিথ হিল

4
@ কীথহিল অন্য কথায়, পাওয়ারশেল অস্তিত্বহীন মূলের একটি পথকে অবৈধ বলে বিবেচনা করে। আমি মনে করি এটি মোটামুটি যুক্তিযুক্ত যেহেতু পাওয়ারশেল এটির সাথে কাজ করার সময় কোন ধরণের সরবরাহকারী ব্যবহার করবেন তা সিদ্ধান্ত নিতে মূল ব্যবহার করে। উদাহরণস্বরূপ, HKLM:\SOFTWAREপাওয়ারশেলের একটি বৈধ পাথ, SOFTWAREলোকাল মেশিন রেজিস্ট্রি হাইভের কীটি উল্লেখ করে । তবে এটি বৈধ কিনা তা নির্ধারণের জন্য, এটি নিবন্ধের পাথগুলির নিয়মগুলি কী তা নির্ধারণ করা দরকার।
jpmc26

3

এই লাইব্রেরিটি ভাল: এনডিপেন্ডে.হেল্পার্স Dফিলডাইরেক্টরিপথ

সম্পাদনা: এটাই আমি নিয়ে এসেছি:

[Reflection.Assembly]::LoadFrom("path\to\NDepend.Helpers.FileDirectoryPath.dll") | out-null

Function NormalizePath ($path)
{
    if (-not $path.StartsWith('.\'))  # FilePathRelative requires relative paths to begin with '.'
    {
        $path = ".\$path"
    }

    if ($path -eq '.\.')  # FilePathRelative can't deal with this case
    {
        $result = '.'
    }
    else
    {
        $relPath = New-Object NDepend.Helpers.FileDirectoryPath.FilePathRelative($path)
        $result = $relPath.Path
    }

    if ($result.StartsWith('.\')) # remove '.\'. 
    {
        $result = $result.SubString(2)
    }

    $result
}

এটিকে কল করুন:

> NormalizePath "fred\frog\..\frag"
fred\frag

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


কেন জানি না কেন এটি একটি ডাউনটায়েট হয়েছিল। সেই পাঠাগারটি পাথের হেরফেরগুলি করার জন্য সত্যই ভাল। এটি আমার প্রকল্পে ব্যবহার করে শেষ করেছি।
ড্যান-জিএফ

বিয়োগ 2 এখনও বিস্মিত। আমি আশা করি যে লোকেরা বুঝতে পারে যে এটি ব্যবহার করা সহজ Power পাওয়ারশেল থেকে নেট সমাবেশ।
ড্যান-জিএফ

এটি সেরা সমাধানের মতো বলে মনে হচ্ছে না তবে এটি পুরোপুরি বৈধ।
জেসনমারচার

@ জেসন, আমি বিশদটি মনে করি না, তবে সেই সময়টিই ছিল সেরা সমাধান কারণ কেবলমাত্র আমার বিশেষ সমস্যাটিই সমাধান করেছিল। এটি তবে সম্ভব যে এর পর থেকে আরও একটি ভাল সমাধান এসেছে।
ড্যান-জিএফ

4
তৃতীয় পক্ষের ডিএলএল হওয়া এই সমাধানের ক্ষেত্রে একটি বড় অসুবিধা
লুই কোটম্যান

1

এটি পুরো পথ দেয়:

(gci 'fred\frog\..\frag').FullName

এটি বর্তমান ডিরেক্টরিটির সাথে সম্পর্কিত পাথ দেয়:

(gci 'fred\frog\..\frag').FullName.Replace((gl).Path + '\', '')

কিছু কারণে তারা শুধুমাত্র যদি কাজ fragএকটি ফাইল, একটি নয় directory


4
জিসিআই হ'ল সন্তানের অধিকারের জন্য একটি নাম। ডিরেক্টরিগুলির শিশুরা এর বিষয়বস্তু। জিআই দিয়ে জিসি প্রতিস্থাপন করুন এবং এটি উভয়ের পক্ষে কাজ করা উচিত।
zdan

4
গেট-আইটেমটি দুর্দান্তভাবে কাজ করেছে। তবে আবারও, এই পদ্ধতির জন্য ফোল্ডারগুলির উপস্থিতি প্রয়োজন।
পিটার লিলভোল্ড

1

একটি ফাংশন তৈরি করুন। এই ফাংশনটি এমন একটি পথকে স্বাভাবিক করবে যেটি আপনার সিস্টেমে অস্তিত্বের পাশাপাশি ড্রাইভের অক্ষর যুক্ত না করে।

function RemoveDotsInPath {
  [cmdletbinding()]
  Param( [Parameter(Position=0,  Mandatory=$true)] [string] $PathString = '' )

  $newPath = $PathString -creplace '(?<grp>[^\n\\]+\\)+(?<-grp>\.\.\\)+(?(grp)(?!))', ''
  return $newPath
}

প্রাক্তন:

$a = 'fooA\obj\BusinessLayer\..\..\bin\BusinessLayer\foo.txt'
RemoveDotsInPath $a
'fooA\bin\BusinessLayer\foo.txt'

রেজিএক্সে সহায়তার জন্য অলিভার স্ক্যাডলিচের জন্য ধন্যবাদ।


লক্ষ করুন somepaththing\.\filename.txtএটি যেমন একক বিন্দু রাখে যেমন পথের জন্য কাজ করে না
মার্ক স্কুলথিস

1

যদি সেই পথটিতে কোনও যোগ্যতা (ড্রাইভ লেটার) অন্তর্ভুক্ত থাকে তবে x0n এর পাওয়ারশেলের উত্তর: অস্তিত্ব না থাকা পথটি সমাধান করুন? পথটি স্বাভাবিক করবে। যদি পথটি কোয়ালিফায়ারকে অন্তর্ভুক্ত না করে, তবে এটি এখনও স্বাভাবিক করা হবে তবে বর্তমান ডিরেক্টরিটির সাথে সম্পর্কিত পুরোপুরি যোগ্য পথটি ফিরিয়ে দেবে, যা আপনি যা চান তা নাও হতে পারে।

$p = 'X:\fred\frog\..\frag'
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p)
X:\fred\frag

$p = '\fred\frog\..\frag'
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p)
C:\fred\frag

$p = 'fred\frog\..\frag'
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($p)
C:\Users\WileCau\fred\frag

0

আপনার যদি .. অংশটি থেকে মুক্তি পাওয়ার দরকার হয় তবে আপনি একটি System.IO.DirectoryInfo অবজেক্টটি ব্যবহার করতে পারেন। কনস্ট্রাক্টরে 'ফ্রেড \ ব্যাঙ .. \ টুকরা' ব্যবহার করুন। পূর্ণ নাম সম্পত্তি আপনাকে সাধারণ ডিরেক্টরি ডিরেক্টরি দেবে।

একমাত্র ব্যর্থতা হ'ল এটি আপনাকে পুরো পথ দেবে (যেমন সি: \ পরীক্ষা \ ফ্রেড \ টুকরা)।


0

এখানে মন্তব্যের সুস্পষ্ট অংশগুলি এমনভাবে মিলিত হয়েছে যে তারা আপেক্ষিক এবং পরম পথকে এক করে দেয়:

[System.IO.Directory]::SetCurrentDirectory($pwd)
[IO.Path]::GetFullPath($dapath)

কিছু নমুনা:

$fps = '.', 'file.txt', '.\file.txt', '..\file.txt', 'c:\somewhere\file.txt'
$fps | % { [IO.Path]::GetFullPath($_) }

আউটপুট:

C:\Users\thelonius\tests
C:\Users\thelonius\tests\file.txt
C:\Users\thelonius\tests\file.txt
C:\Users\thelonius\file.txt
c:\somewhere\file.txt

-1

ঠিক আছে, একটি উপায় হবে:

Join-Path 'fred\frog' '..\frag'.Replace('..', '')

অপেক্ষা করুন, আমি প্রশ্নটি ভুল বুঝতে পারি। আপনার উদাহরণে, টুকরাটি ব্যাঙের একটি সাবফোল্ডার?


"ভঙ্গুর কি ব্যাঙের একটি সাবফোল্ডার?" না .. মানে এক স্তর উপরে যেতে। ফ্রেড ফ্রেডে একটি সাবফোল্ডার (বা একটি ফাইল)।
ড্যান-জিএফ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.