পাওয়ারশেলে কোনও পথ রয়েছে কিনা তা যাচাই করার আরও ভাল উপায়


122

আমি কেবল এর বাক্য গঠনটি পছন্দ করি না:

if (Test-Path $path) { ... }

এবং

if (-not (Test-Path $path)) { ... }
if (!(Test-Path $path)) { ... }

বিশেষত অনেকগুলি প্রথম বন্ধনী রয়েছে এবং এ জাতীয় প্রচলিত ব্যবহারের জন্য "অস্তিত্ব নেই" পরীক্ষা করার সময় খুব পঠনযোগ্য হয় না। এটি করার একটি ভাল উপায় কি?

আপডেট: আমার বর্তমান সমাধানটি হ'ল এলিয়াসগুলি এখানে ব্যবহার করা existএবং তার জন্য not-existব্যাখ্যা করা

পাওয়ারশেল সংগ্রহস্থলে সম্পর্কিত সমস্যা: https://github.com/PowerShell/Powershell/issues/1970


2
আপনি ব্যবহার করতে পারেনtry{ Test-Path -EA Stop $path; #stuff to do if found } catch { # stuff to do if not found }
এরিস

1
সম্পর্কিত ইস্যু: github.com/PowerShell/Powershell/issues/1970
ওরাড

উত্তর:


130

আপনি যদি কেবলমাত্র বিশেষত ফাইলগুলির জন্য সেমিডলেট সিনট্যাক্সের বিকল্প চান তবে। File.Exists()নেট পদ্ধতিটি ব্যবহার করুন :

if(![System.IO.File]::Exists($path)){
    # file with path $path doesn't exist
}

অন্যদিকে, আপনি যদি একটি সাধারণ উদ্দেশ্যে অবহেলিত উপন্যাস চান Test-Pathতবে আপনার কীভাবে এটি করা উচিত তা এখানে:

# Gather command meta data from the original Cmdlet (in this case, Test-Path)
$TestPathCmd = Get-Command Test-Path
$TestPathCmdMetaData = New-Object System.Management.Automation.CommandMetadata $TestPathCmd

# Use the static ProxyCommand.GetParamBlock method to copy 
# Test-Path's param block and CmdletBinding attribute
$Binding = [System.Management.Automation.ProxyCommand]::GetCmdletBindingAttribute($TestPathCmdMetaData)
$Params  = [System.Management.Automation.ProxyCommand]::GetParamBlock($TestPathCmdMetaData)

# Create wrapper for the command that proxies the parameters to Test-Path 
# using @PSBoundParameters, and negates any output with -not
$WrappedCommand = { 
    try { -not (Test-Path @PSBoundParameters) } catch { throw $_ }
}

# define your new function using the details above
$Function:notexists = '{0}param({1}) {2}' -f $Binding,$Params,$WrappedCommand

notexistsএখন ঠিক মত আচরণ করবে Test-Path, কিন্তু সর্বদা বিপরীত ফলাফল ফিরে আসবে:

PS C:\> Test-Path -Path "C:\Windows"
True
PS C:\> notexists -Path "C:\Windows"
False
PS C:\> notexists "C:\Windows" # positional parameter binding exactly like Test-Path
False

যেমন আপনি ইতিমধ্যে নিজেকে দেখিয়েছেন, বিপরীতটি বেশ সহজ, কেবলমাত্র উপনামের existsজন্য Test-Path:

PS C:\> New-Alias exists Test-Path
PS C:\> exists -Path "C:\Windows"
True

1
যদি $pathপাওয়ারশেল সরবরাহকারীর মতো "বিশেষ" হয় (মনে করুন এইচকেএলএম: \ সফটওয়্যার think ...) তবে এটি খারাপভাবে ব্যর্থ হবে।
এরিস

4
@ এরিস প্রশ্নটি বিশেষত কোনও ফাইল উপস্থিত রয়েছে কিনা তা যাচাই করতে বলে
ম্যাথিয়াস আর জেসেন

1
অবশ্যই, এবং ফ্লাইতে একটি নতুন সেমিডলেট তৈরি করা ঝরঝরে। প্রায় কোনও উপনামের মতো অপ্রতিরোধ্য, তবে এখনও সত্যই ঝরঝরে :)
এরিস

নিস! আমি মনে করি PS এর জন্য দেশীয় সমর্থন যুক্ত করা উচিত।
ওড়াদ

4
@ আমি আপনাকে গুরুতরভাবে সন্দেহ করতে পেরেছি যে আপনি তাদের এটি করতে পেরেছেন। "অনেক বেশি বন্ধনী" একটি অত্যন্ত বিষয়গত যুক্তি এবং ভাষার নকশা / নির্দিষ্টকরণ থেকে সত্যই বিচ্যুত হওয়ার যোগ্য নয়। এফডব্লিউআইডাব্লু, আমি যদি / ব্রায়েন্টিস্ট দ্বারা প্রস্তাবিত আরও ভাল বিকল্প হিসাবে যদি আপনি সত্যিই এতটা প্রথম বন্ধনী ঘৃণা করেন তবে আমিও তার সাথে একমত:if(Test-Path $path){}else{ # do your thing }
ম্যাথিয়াস আর জেসেন

38

আপনার পোস্ট করা উপনাম সমাধানটি চতুর, তবে আমি স্ক্রিপ্টগুলিতে এর ব্যবহারের বিরুদ্ধে তর্ক করব, একই কারণে আমি স্ক্রিপ্টগুলিতে কোনও এলিয়াস ব্যবহার করতে পছন্দ করি না; এটি পাঠযোগ্যতার ক্ষতি করতে পারে।

যদি আপনি নিজের প্রোফাইলে এটি যুক্ত করতে চান তবে আপনি দ্রুত কমান্ডগুলি টাইপ করতে পারেন বা এটি শেল হিসাবে ব্যবহার করতে পারেন, তবে আমি বুঝতে পারছিলাম।

পরিবর্তে আপনি পাইপিং বিবেচনা করতে পারেন:

if ($path | Test-Path) { ... }
if (-not ($path | Test-Path)) { ... }
if (!($path | Test-Path)) { ... }

বিকল্পভাবে, নেতিবাচক পদ্ধতির জন্য, আপনার কোডের জন্য উপযুক্ত হলে, আপনি এটি একটি ইতিবাচক চেক করতে পারেন elseতবে নেতিবাচকদের জন্য ব্যবহার করুন:

if (Test-Path $path) {
    throw "File already exists."
} else {
   # The thing you really wanted to do.
}

1
আমি এখানে পাইপিং পছন্দ করি তবে নেতিবাচকদের জন্য আপনার প্রস্তাবিত চেকগুলি প্রথম বন্ধনী ছাড়াই ভুল, বা এটি সর্বদা মূল্যায়ন করবে False। আপনার এটি পছন্দ করা উচিত if (-not ($path | Test-Path)) { ... }
ওড়াদ

1
@ আপনি ঠিক আছেন! আসলে এটি সেই ক্ষেত্রে পাইপিংয়ের একটি নেতিবাচক। আমি ব্যর্থতা ছুঁড়ে না ফেলে নিরাপত্তার এক মিথ্যা অনুভূতিতে জড়িয়ে পড়েছিলাম, যখন সত্য যে এটি ব্যর্থ হয়েছিল। এটিকে আসল উপায়ে বলা একটি ব্যতিক্রম ছুঁড়েছে, সমস্যাটি ধরা সহজ করে তোলে।
ব্রিটিশবাদী

10

নিম্নলিখিত উপকরণ যুক্ত করুন। আমি মনে করি এগুলি ডিফল্টরূপে পাওয়ারশেলে উপলব্ধ করা উচিত:

function not-exist { -not (Test-Path $args) }
Set-Alias !exist not-exist -Option "Constant, AllScope"
Set-Alias exist Test-Path -Option "Constant, AllScope"

এটির সাথে, শর্তাধীন বিবৃতিগুলি এতে পরিবর্তিত হবে:

if (exist $path) { ... }

এবং

if (not-exist $path)) { ... }
if (!exist $path)) { ... }

4
আপনি যদি পাওয়ারশেল টিমটি "অস্তিত্ব" উপন্যাস যুক্ত করতে চান তবে আপনার মাইক্রোসফ্ট সংযোগের মাধ্যমে একটি বৈশিষ্ট্য অনুরোধ জমা দিতে হবে
ম্যাথিয়াস আর জেসেন

1
যদিও আমি নিজেই এর উত্তর দিয়েছি, আমি @ ম্যাথিয়াস-আর-জেসেনের উত্তর গ্রহণ করি কারণ এটি পরামিতিগুলি আরও ভাল পরিচালনা করে।
অরেড

2

অন্য বিকল্পটি হ'ল ব্যবহার করা IO.FileInfoযা আপনাকে এ জাতীয় ফাইলের তথ্য দেয় যা কেবলমাত্র এই ধরণের ব্যবহার করে জীবনকে সহজ করে তোলে:

PS > mkdir C:\Temp
PS > dir C:\Temp\
PS > [IO.FileInfo] $foo = 'C:\Temp\foo.txt'
PS > $foo.Exists
False
PS > New-TemporaryFile | Move-Item -Destination C:\Temp\foo.txt
PS > $foo.Refresh()
PS > $foo.Exists
True
PS > $foo | Select-Object *


Mode              : -a----
VersionInfo       : File:             C:\Temp\foo.txt
                    InternalName:
                    OriginalFilename:
                    FileVersion:
                    FileDescription:
                    Product:
                    ProductVersion:
                    Debug:            False
                    Patched:          False
                    PreRelease:       False
                    PrivateBuild:     False
                    SpecialBuild:     False
                    Language:

BaseName          : foo
Target            : {}
LinkType          :
Length            : 0
DirectoryName     : C:\Temp
Directory         : C:\Temp
IsReadOnly        : False
FullName          : C:\Temp\foo.txt
Extension         : .txt
Name              : foo.txt
Exists            : True
CreationTime      : 2/27/2019 8:57:33 AM
CreationTimeUtc   : 2/27/2019 1:57:33 PM
LastAccessTime    : 2/27/2019 8:57:33 AM
LastAccessTimeUtc : 2/27/2019 1:57:33 PM
LastWriteTime     : 2/27/2019 8:57:33 AM
LastWriteTimeUtc  : 2/27/2019 1:57:33 PM
Attributes        : Archive

আমার ব্লগে আরও বিশদ।


1

ডিরেক্টরিতে কোনও পাথ রয়েছে কিনা তা পরীক্ষা করতে এটি ব্যবহার করুন:

$pathToDirectory = "c:\program files\blahblah\"
if (![System.IO.Directory]::Exists($pathToDirectory))
{
 mkdir $path1
}

কোনও ফাইলের কোনও পথ উপস্থিত রয়েছে কিনা তা পরীক্ষা করতে @ ম্যাথিয়াস কী প্রস্তাবিত তা ব্যবহার করুন :

[System.IO.File]::Exists($pathToAFile)

0

এটি করার জন্য এটি আমার ক্ষমতাশালী নবাগত পদ্ধতি

if ((Test-Path ".\Desktop\checkfile.txt") -ne "True") {
    Write-Host "Damn it"
} else {
    Write-Host "Yay"
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.