यह देखने के लिए एक बेहतर तरीका है कि पावरशेल में कोई रास्ता मौजूद है या नहीं


123

मुझे सिंटैक्स पसंद नहीं है:

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

तथा

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

विशेष रूप से बहुत अधिक कोष्ठक है और बहुत आम नहीं है जब इस तरह के एक आम उपयोग के लिए "मौजूद नहीं" की जाँच हो। ऐसा करने का एक बेहतर तरीका क्या है?

अद्यतन: मेरा वर्तमान समाधान के लिए existऔर यहाँnot-exist बताया गया है कि उपनाम का उपयोग करना है

PowerShell रिपॉजिटरी में संबंधित समस्या: 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
orad

जवाबों:


130

यदि आप विशेष रूप से फ़ाइलों के लिए cmdlet सिंटैक्स का विकल्प चाहते हैं, तो File.Exists().NET विधि का उपयोग करें :

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"विशेष" है, जैसे कि Powershell प्रदाता (HKLM: \ SOFTWARE \ ...) पर तो यह बुरी तरह विफल हो जाएगा।
एरिस

4
@ कोई सवाल विशेष रूप से यह जांचने के लिए कहता है कि कोई फ़ाइल मौजूद है या नहीं
मथियास आर जेसेन

1
निश्चित रूप से, और मक्खी पर एक नया cmdlet बनाना साफ है। लगभग उर्फ ​​के रूप में अस्वीकार्य है, लेकिन अभी भी बहुत साफ है :)
एरिस

अच्छा! मुझे लगता है कि पीएस को इसके लिए मूल समर्थन जोड़ना चाहिए।
20

4
@ मुझे गंभीरता से संदेह है कि आप उन्हें ऐसा करने के लिए मिलेंगे। "बहुत अधिक कोष्ठक" एक बहुत ही व्यक्तिपरक तर्क है और वास्तव में भाषा डिजाइन / विनिर्देशन से भटकाने वाला नहीं है। FWIW, मैं भी सहमत हूं कि अगर @Briantist द्वारा प्रस्तावित एक और विकल्प के रूप में एक बेहतर विकल्प के रूप में यदि आप वास्तव में कोष्ठक से घृणा करते हैं:if(Test-Path $path){}else{ # do your thing }
Mathias R. Jessen

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)) { ... }
orad

1
@ आप सही हैं! वास्तव में यह उस मामले में पाइपिंग का एक नकारात्मक है। मुझे सुरक्षा के झूठे अर्थों में यह एक अपवाद नहीं फेंकने के रूप में दिया गया था, जब यह तथ्य यह विफल हो रहा था। इसे मूल तरीके से कॉल करना एक अपवाद को फेंक देता है, जिससे समस्या को पकड़ना आसान हो जाता है।
रिश्वतखोर

10

निम्नलिखित उपनाम जोड़ें। मुझे लगता है कि इन्हें डिफ़ॉल्ट रूप से PowerShell में उपलब्ध कराया जाना चाहिए:

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
यदि आप चाहते हैं कि PowerShell टीम "अस्तित्व" उपनाम को जोड़ दे, तो आपको Microsoft Connect
Mathias R. Jessen

1
भले ही मैंने स्वयं इसका उत्तर दिया हो, मैं @ mathias-r-jessen का उत्तर स्वीकार करता हूं क्योंकि यह मापदंडों को बेहतर तरीके से संभालता है।
orad

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
}

यह जाँचने के लिए कि क्या किसी फ़ाइल का पथ मौजूद है, जिसका उपयोग @Mathias ने किया है:

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

0

यह ऐसा करने का मेरा नया तरीका है

if ((Test-Path ".\Desktop\checkfile.txt") -ne "True") {
    Write-Host "Damn it"
} else {
    Write-Host "Yay"
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.