PowerShell 文件存在性检查返回假阴性

标签 powershell

很简单,我需要使用 PowerShell 检查用户主驱动器中是否存在文件。此脚本将在一组机器上执行,因此路径需要是相对的。

电流输出:

# Create file named 'foo' in home dir
New-Item '~/foo'

# Check if the file exists
[System.IO.File]::Exists('~/foo')
# Returns false

列出文件表明它确实存在:
ls '~/foo'

Directory: C:\Users\tom_n


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----           20/02/2018 14:13              0 foo

我在这里遗漏了一些明显的东西吗?我还使用具有实际大小的文件对此进行了测试,但也无济于事。

我很欣赏任何输入

最佳答案

tl;博士 :

请勿使用 ~ - 使用 $HOME 引用当前用户的主目录,通常在 "..." 内:

[System.IO.File]::Exists("$HOME/foo")

或者,最好使用 PowerShell 的 Test-Path小命令:
Test-Path -LiteralPath "$HOME/foo"

笔记:
* PowerShell 和 .NET 类型接受 /\可互换地作为路径分隔符;考虑到潜在的跨平台兼容性,请选择 / .
* 严格来说,自 "$HOME/foo"传递给 Test-Path在参数模式(命令行样式)中,包含在 "..." 中在这种情况下不需要(尝试 Write-Output $HOME/foo ),但包含在 "..." 中是一个养成的好习惯,因为它适用于更广泛的场景。


PowerShell 的 ~不完全等同于 ~在 Unix 上 (在类似 POSIX 的 shell 中)并且在 PowerShell 中可能无法按照您期望的方式工作:

如解释 in this TechNet article [1], ~在 PowerShell 中是指由当前位置的驱动器提供程序定义的主位置,哪一个:
  • 可能是也可能不是文件系统。
  • 可能会或可能不会被定义。

  • 在 Windows 上,请考虑以下使用注册表驱动器提供程序的示例:
    Set-location HKCU:\Software
    Set-Location ~
    

    这会产生以下错误:
    Set-Location : Home location for this provider is not set. To set the home location, call "(get-psprovider 'Registry').Home = 'path'".
    ...
    

    如您所见,因为当前位置位于注册表提供程序的驱动器上,~被解释为该提供商对家庭位置的想法,但是,恰好没有定义。

    一个额外的关键区别:
  • 在 Unix 上,~是一个 shell 特性:它必须不加引号地使用,在这种情况下,它会被 shell 扩展到完整的文字主目录。 , 在目标命令看到路径之前,这样目标命令看到的是文字路径并且不需要知道 ~ ,事实上,标准实用程序并不知道 ~ ,您可以通过对比 ls ~ 来验证(好)与 ls '~' (尝试列出字面上名为 ~ 的文件/目录)。
  • 在 PowerShell 中,~是 PowerShell 驱动器提供程序功能 :~按原样传递给驱动器提供程序 cmdlet,例如 Get-ChildItem他们解释 ~指的是当前驱动器的主位置。 外部实用程序(例如,Windows 上的 findstr.exe)和 .NET Framework 不遵循此约定 因此解释~作为文字文件名。


  • 相比之下, automatic variable $HOME 是 PowerShell 等效于 Unix ~ ,增加了灵活性:

    而 Unix ~必须不加引号才能扩展到用户的主目录,PowerShell 的自动 $HOME变量也可以在双引号字符串中引用(作为正常字符串扩展(插值)的一部分)。

    最后, .NET 类型,例如 [System.IO.File]自己都不支持 ~也不是 $HOME ,但通过使用 "$HOME/..." PowerShell 确保 $HOME在将路径字符串传递给 .NET 方法之前,将替换为实际的、文字主目录路径。

    [1] Get-Help about_Locations Get-Help about_Path_Syntax ,有关该主题的官方帮助主题,应包含有关 ~ 的信息。 ,
    但在撰写本文时还没有。

    关于PowerShell 文件存在性检查返回假阴性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48887329/

    相关文章:

    powershell - Powershell子类构造函数-找不到 “new”的重载

    windows - 将文件添加到文件夹时运行 .bat 文件的 Powershell 脚本

    datetime - 在 PowerShell 中,如何将 DateTime 转换为 UNIX 时间?

    windows - 使用键盘快捷键启动 powershell 脚本

    PowerShell:如何设置文化?

    windows - 运行带有 Git 命令的远程 PowerShell 脚本会导致 NativeCommandError

    c# - 使用 ProjectItems.item

    powershell - PowerShell for-each循环输出到文件

    blackberry - 将 Powershell 变量传递到脚本 block 中

    powershell - 使用 Powershell 将匹配的输出导出到 CSV 作为第 1 列和第 2 列