windows 命令提示符/powershell 中的 Globbing 模式

Globbing patterns in windows command prompt/ powershell

我想知道是否有任何方法可以在 windows 上实现此行为,例如:

/b?n/ca? /etc/pa??wd -> 执行 'cat /etc/passwd'

在 PowerShell 中,您可以使用 Resolve-Path,它 解析路径中的通配符,并显示路径内容。

示例:我想从通常驻留在“c:\Program Files (x86)\Windows Kits\bin.0.19041 中的 Windows SDK 中找到 signtool.exe .0\x64\signtool.exe”,其中可能安装了任何其他版本。

所以我可以使用:Resolve-Path 'c:\program*\Windows Kits\bin\*\x64\signtool.exe'

编辑:

如果你想直接执行它,你可以使用 & 调用运算符,例如

&(Resolve-Path 'c:\wind?ws\n?tepad.exe')

  • 除了 PowerShell 中的有限例外,Windows 支持 shell-level globbing - 目标命令必须执行它们自己的通配符模式解析 以匹配文件名;如果他们不这样做,则必须 手动 执行 globbing,并将结果作为文字路径传递;有关背景信息,请参阅底部。

  • PowerShell:

    • 也许令人惊讶的是,您可以通过通配符模式调用可执行文件,正如zett42指出的那样,尽管 该行为存在问题(见底部部分):

      # Surprisingly DOES find C:\Windows\System32\attrib.exe
      # and invokes it.
      C:\Windows\System3?\attr*.exe /?
      
      • 通常,您可以通过 Get-Command cmdlet 发现命令,包括外部程序。
    • PowerShell 中的许多 file-processing cmdlet do 执行它们自己的 globbing(例如,Get-ChildItemRemove-Item);如果您正在调用不执行的命令,特别是不执行的外部程序,则必须执行通配 手动 ,预先 Unix 除外 调用外部程序时类似平台,其中 PowerShell 确实 执行自动通配(见底部):

      • 使用 Convert-Path 获取匹配文件或目录的完整 file-system-native 路径。

        • 虽然 Resolve-Path 也可以工作,但它 returns 对象 您需要访问其 .ProviderPath 属性 才能获得相同的信息(将这些对象字符串化,当您将它们传递给外部程序时隐式发生,产生它们的 .Path 属性,这可能基于 PowerShell-only 驱动外部程序和 .NET API 对此一无所知。)
      • 为了更好地控制匹配的内容,请使用 Get-ChildItem 并根据需要访问结果对象的 .Name.FullName 属性;例如,Get-ChildItem 允许您将匹配限制为 文件 (-File) 或 目录 (-Directory ) 而已。

      • PowerShell 可以轻松地以编程方式使用手动执行的通配结果;以下示例将当前目录中所有 *.txt 文件的完整路径作为单独的参数传递给 cmd.exeecho 命令;如果需要,PowerShell 会自动用 "..." 中的空格括起路径:

         cmd /c echo (Get-ChildItem -Filter *.txt).FullName
        
      • 一般来说,请注意 PowerShell 的 wildcard patterns 比主机平台的 file-system API 更强大,并且特别包括对字符集的支持(例如 [ab] ) 和范围(例如 [0-9]);另一个重要区别是 ? 只匹配 一个 字符,而 Windows 上的原生 file-system API 匹配 none 或一个.

        • 但是,当使用 file-processing cmdlet 的 -Filter 参数(例如 Get-ChildItem)时,会使用 主机平台的 模式,即 -同时限制功能 - 提高性能;一个警告是,在 Unix-like 平台上 ? 然后看起来像在 Windows 上一样,即导致它匹配 none 或一个 字符.
  • cmd.exe(命令提示符,遗留 shell):

    • cmd.exe 支持通过通配符模式调用 executables一些 cmd.exe 的内部命令(例如,dirdel)和 一些 标准外部程序(例如,attrib.exedo 执行它们自己的 globbing;否则你必须手动 ,预先 :

      • where.exe,用于发现外部程序的外部程序基本上只支持可执行文件names中的通配符模式(例如where find*.exe),不在 路径 中,这限制 wildcard-based 查找位于 PATH 环境变量中列出的目录中的可执行文件。

        :: OK - "*" is part of a *name* only
        where.exe find*.exe
        
        :: !! FAILS: "*" or "?" must not be part of a *path*
        :: !! -> "ERROR: Invalid pattern is specified in "path:pattern"."
        where.exe C:\Windows\System32\find*.exe
        
      • 通配符 dir 似乎仅限于 last 路径组件中的通配符:

        :: OK - "*" is only in the *last* path component.
        dir C:\Windows\System32\attri*
        
        :: !! FAILS: "*" or "?" must not occur in *non-terminal* components.
        :: !! -> "The filename, directory name, or volume label syntax is incorrect."
        dir C:\Windows\System3?\attri*
        
      • 以编程方式使用手动通配结果cmd.exe[中非常麻烦 并且需要使用 for 语句(其通配符匹配与 dir 命令具有相同的限制);例如,使用 批处理文件 .cmd.bat 文件)的语法:

        • 使用解析后的可执行文件路径进行调用(假设只有一个个文件匹配):

          @echo off
          setlocal
          
          :: Use a `for` loop over a wildcard pattern to enumerate
          :: the matching filenames - assumed to be just *one* in this case,
          :: namely attrib.exe, and save it in a variable.
          for %%f in (C:\Windows\System32\attr*.exe) do set "Exe=%%f"
          
          :: Execute the resolved filename to show its command-line help.
          "%Exe%" /?             
          
        • 要将匹配的文件名作为多个参数传递给单个命令:

          @echo off
          setlocal enableDelayedExpansion
          
          :: Use a `for` loop over a wildcard pattern to enumerate
          :: matching filenames and collect them in a single variable.
          set files=
          for %%f in (*.txt) do set files=!files! "%%f"
          
          :: Pass all matching filenames to `echo` in this example.
          echo %files%
          

背景资料:

  • Unix类平台上,POSIX-compatibleshell如Bash他们自己执行globbin(将文件名通配符模式解析为匹配的文件名), 之前目标命令看到生成的文件名,作为名为 [=79= 的功能集的一部分](link 是 Bash 手册)。

  • Windowscmd.exe(遗留 shell也称为命令提示符)不执行此类扩展,而 PowerShell 大部分.

    • 也就是说,通常每个目标命令解释通配符模式并解析它们匹配文件名。

      • 也就是说,在 PowerShell 中,许多 built-in 命令,称为 cmdletsdo 支持PowerShell 的 wildcard patterns,特别是通过 provider cmdlet 的 -Path 参数,例如 Get-ChildItem.

      • 此外,更普遍的是,表示 names 的 cmdlet 参数通常也支持通配符;例如,Get-Process exp* 列出映像名称以 exp 开头的所有进程,例如 explorer.

      • 请注意 Unix-style shell 对 Windows 的扩展也意味着 没有 语义区分在 unquotedquoted 参数之间(例如,*.txt"*.txt"):目标命令通常会看到 两者作为逐字*.txt.

    • PowerShell 中,在这些 有限的情况下 会发生自动通配 ]:

      • 也许令人惊讶的是,一个可执行文件文件路径可以通过通配符模式:

        • as-is,如果模式未包含在 '...'"..." 中 and/or 不包含变量引用或表达式;例如:

           C:\Windows\System3?\attri?.exe
          
        • 通过&call operator,否则;例如:

           & $env:SystemRoot\System32\attri?.exe
          
        • 但是,此功能的实用性值得怀疑 - 您什么时候不想预先知道什么特定的 您正在调用的可执行文件? - 鉴于其他上下文中不适当的通配符处理表面也存在,目前尚不清楚它是否 通过设计 实现 - 参见 GitHub issue #4726

          • 此外,至少在 PowerShell 7.2.4 之前,如果 两个或更多 可执行文件匹配通配符模式,则会出现误导性错误,提示 未找到 匹配的可执行文件 - 请参阅 GitHub 问题 #17468;问题的一个变体也会影响传递 wildcard-based path(与仅仅 name 相对)匹配多个可执行文件到 Get-Command.

          • 在POSIX-compatibleshells中,multi-match场景处理不同,但同样没用:第一个 匹配的可执行文件被调用,所有其他的都被传递 作为它的参数.

      • 仅在 Unix-like 平台上,PowerShell 模拟 POSIX-compatible shells 调用外部程序时,努力表现得更像platform-native shells;如果 PowerShell 不这样做,那么像 ls *.txt 这样简单的事情就会失败,因为外部 /bin/ls 实用程序随后会收到 verbatim *.txt 作为它的论点。

        • 但是,从 PowerShell 7.2.4 开始,此 模拟具有局限性
          • 无法使用包含 空格 的通配符模式 - 请参阅 GitHub issue #10683
          • 无法包含 隐藏的 文件 - 请参阅 GitHub issue #4683
          • 一静experimental feature, available in preview versions of 7.3, PSNativePSPathResolution, automatically translates wildcard patterns based on PowerShell-only drives to their underlying native file-system paths; however, this feature is currently overzealous - see GitHub issue #13640 - and inherently bears the risk of false positives - see GitHub issue #13644