【问题标题】:Tab completion problem using start in Powershell在 Powershell 中使用 start 的选项卡完成问题
【发布时间】:2021-10-05 04:20:51
【问题描述】:

我想在 powershell 中打开[test].txt,但是当我在键盘上按 Tab 时,它会自动完成如下:

start '.\`[test`].txt'

并生成此错误:

start:由于错误无法运行此命令:系统找不到指定的文件。 在行:1 个字符:1 + 开始'.`[test`].txt' + ~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo: InvalidOperation: (:) [Start-Process], InvalidOperationException + FullQualifiedErrorId:InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand

我想在按制表符时删除反引号字符。我该怎么做?

【问题讨论】:

  • 使用-LiteralPath 参数传递包含通配符的文件名/路径,例如:Invoke-Item -LiteralPath '.\[test].txt'。如果这不起作用,请确保您位于文件所在的正确目录中

标签: powershell


【解决方案1】:

补充Mathias R. Jessen's helpful answer

您看到的是 PowerShell 的选项卡补全限制(至少 PowerShell Core 7.2.0-preview.9):

  • 您正在使用制表符完成 Start-Process cmdlet 的 - 位置隐含 - -FilePath 参数的值(start 是它的内置别名)。

  • 由于-FilePath 只接受literal(逐字)文件路径,not 也是通配符模式,制表符补全应导致.\[test].txt没有 `-转义wildcard-模式元字符[]

相比之下,Invoke-Item(其内置别名是 ii确实通过其 -Path 参数支持通配符模式 - 以及 literal(逐字)通过其-LiteralPath 参数的路径:

  • 由于-Path 位于Invoke-Item's 默认 parameter set 并且是第一个位置参数,如果您使用Invoke-Item,tab-completed 值将按原样工作而不是Start-Process

    # OK with tab-completion: positionally binds to -Path
    Invoke-Item '.\`[test`].txt'
    
  • 事实上,tab-completion 知道手头的参数何时会绑定到-LiteralPath 参数,然后执行转义:

    # OK with tab-completion: due to explicitly targeting -LiteralPath,
    # no escaping is performed.
    Invoke-Item -LiteralPath .\[test].txt 
    
  • 以上适用于所有provider cmdlet,例如Get-ChildItemGet-Content(粗略地说,它们包含带有单词ItemContentProperty 以他们的名义)。


未来可能的增强功能:

  • PowerShell 的制表符补全逻辑目前已硬连接到:

    • 默认为转义完成,
    • 除非目标参数名称(如果已知)恰好是-LiteralPath
  • GitHub issue #14149提议:


何时使用Start-ProcessInvoke-Item

  • 简单地说,Start-ProcessInvoke-Item超集;前者通常用于启动 GUI 可执行文件,而后者通常用于打开文档,其中注册了处理它们的应用程序或 目录文件资源管理器(在 Windows 上)。

  • 虽然Start-Process 可以做所有Invoke-Item 可以做的甚至更多,一个关键的区别相当于一个陷阱Start-Process$env:PATH first 中列出的目录中查找仅按名称标识的文件或目录,而不是 em> 在当前目录中; 在名称前加上.\(或使用完整路径)可以避免这种歧义。

# Unambiguously targets .\file.txt, i.e. a file in the *current* dir.
# In other words: The same as:
#   Invoke-Item .\file.txt
Invoke-Item file.txt

# AMBIGUOUS:
# !! *First* looks for a file.txt file in the directories
# !! listed in $env:PATH and opens the first one it finds.
# !! Only if none is found does it look in the current dir.
Start-Process file.txt

# OK - unambiguously looks in the current dir. only, thanks to ".\"
Start-Process .\file.txt

注意:

  • 由于 Start-Process 通常用于启动可执行文件GUI 可执行文件;除非特殊情况,否则它是错误的启动工具控制台应用程序),查看$env:PATH(首先)是有道理的,但该行为也扩展到文档-可执行文件)是意外且有问题的 - 请参阅GitHub issue #9469

从好的方面来说,Start-Process(不像Invoke-Item可以在默认的网络浏览器中打开URLs;例如:

Start-Process http://example.org

总结

  • 始终使用Start-Process 代替Invoke-Item 很好,只要您通过在当前 目录中的目标项目前加上.\ 前缀来避免歧义 - 幸运的是,制表符完成对于当前目录中的项目。自动添加此前缀。

【讨论】:

    【解决方案2】:

    startStart-Process 的别名)实际上是为启动可执行文件或外部命令而设计的。

    要调用与任意文件关联的默认 shell 处理程序,请改用 Invoke-Item

    为了避免 PowerShell 尝试将 [...] 解释为通配符模式,请使用 -LiteralPath 参数:

    Invoke-Item -LiteralPath '.\[test].txt'
    

    所有项目提供程序 cmdlet(*-Item*-ChildItem)都支持文字路径绑定,因此当您拥有确切路径时,它始终是最佳/更安全的选择。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多