如何在Powershell下查找当前目录下是否存在文件?

How to find if a file exists under current directory under Powershell?

题目看起来很简单,我下面用的方法应该可以,但是不行:

PS C:\Users\John.Smith\Downloads> rm .\uucode.ps1
PS C:\Users\John.Smith\Downloads> [System.IO.File]::Exists("uucode.ps1")
True
PS C:\Users\John.Smith\Downloads> [System.IO.File]::Exists(".\uucode.ps1")
True

我删除了文件,但它仍然显示文件存在。我发现它正在寻找我的主目录下的文件(即使指定了“.”):

PS C:\Users\John.Smith\Downloads> rm ..\uucode.ps1
PS C:\Users\John.Smith\Downloads> [System.IO.File]::Exists("uucode.ps1")
False
PS C:\Users\John.Smith\Downloads> [System.IO.File]::Exists(".\uucode.ps1")
False

这是错误还是什么?我使用的 OS 和 Powershell 版本是:

PS C:\Users\John.Smith\Downloads> (Get-WmiObject -class Win32_OperatingSystem).Caption
Microsoft Windows Server 2012 R2 Standard

PS C:\Users\John.Smith\Downloads> $psversiontable.psversion
Major  Minor  Build  Revision
-----  -----  -----  --------
5      1      14409  1005

我自己能想到的一个解决方案是使用pwd找到当前目录,并检查提供给我的文件是否是相对路径(不是以\或/开头),然后加入当前目录与相对路径,但我认为应该有更简单的方法,你能帮我吗?谢谢

Is this a bug or something?

不,此行为是预期的。

.NET 方法采用相对路径作为参数,将相对于调用进程的 工作目录解析它们 - 并且 powershell.exe 不会更新其当前工作目录在 PowerShell 本身内部的位置之间导航时的目录:

PS C:\Users\John.Smith> [System.Environment]::CurrentDirectory
C:\Users\John.Smith
PS C:\Users\John.Smith> cd Downloads
PS C:\Users\John.Smith\Downloads> [System.Environment]::CurrentDirectory
C:\Users\John.Smith

您可以通过仅传递根文件系统路径来解决它:

PS C:\Users\John.Smith\Downloads> [System.IO.File]::Exists("$PWD\uucode.ps1")
PS C:\Users\John.Smith\Downloads> [System.IO.File]::Exists('C:\Users\John.Smith\Downloads\uucode.ps1')

... 或者,最好坚持使用 PowerShell 的提供程序 cmdlet - 在 FileSystem 位置时,Test-Path -PathType Leaf 相当于 [File]::Exists():

PS C:\Users\John.Smith\Downloads> Test-Path .\uucode.ps1 -PathType Leaf # always correctly resolves path relative to $PWD

如果您希望 PowerShell 始终更新主机应用程序进程的当前工作目录,您可以 do so in the prompt function

$function:prompt = {
  # Need to check that we're in the file system - can't set process directory to a registry path for example
  if ($PWD.Provider.Name -eq 'FileSystem') {
    [System.IO.Directory]::SetCurrentDirectory($PWD)
  }
  return "PS $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) "
}