【问题标题】:Drag and Drop to a Powershell script拖放到 Powershell 脚本
【发布时间】:2021-11-11 05:23:04
【问题描述】:

我以为我有一个答案,但我玩得越多,我就越认为它是 Powershell 的设计缺陷。

我想通过拖放(或使用发送至机制)将多个文件和/或文件夹作为数组传递给 Powershell 脚本。

测试脚本

#Test.ps1
param ( [string[]] $Paths, [string] $ExampleParameter )
"Paths"
$Paths
"args"
$args

尝试 #1

我使用以下命令行创建了一个快捷方式,并将一些文件拖到上面。这些文件作为单独的参数出现,首先在位置上匹配脚本参数,其余的放在 $args 数组中。

尝试 #1 的快捷方式

powershell.exe -noprofile -noexit -file c:\Test.ps1

包装脚本

我发现我可以使用包装脚本来做到这一点...

#TestWrapper.ps1
& .\Test.ps1 -Paths $args

包装脚本的快捷方式

powershell.exe -noprofile -noexit -file c:\TestWrapper.ps1

批处理文件包装脚本

它通过批处理文件包装脚本工作......

REM TestWrapper.bat
SET args='%1'
:More
SHIFT
IF '%1' == '' GOTO Done
SET args=%args%,'%1'
GOTO More
:Done
Powershell.exe -noprofile -noexit -command "& {c:\test.ps1 %args%}"

尝试的答案

Keith Hill 让优秀的suggestion 使用以下快捷命令行,但是它没有正确传递参数。带有空格的路径在到达 Test.ps1 脚本时被分开。

powershell.exe -noprofile -noexit -command "& {c:\test1.ps1 $args}"

有没有人找到无需额外脚本的方法?

【问题讨论】:

  • 这是一个替代解决方案,虽然它会need to be adapted to powershell
  • 记录在案...如果使用 Powershell -File ScriptName.ps1 运行脚本并且脚本没有参数块,则 $args 变量将包含预期的内容,即文件路径。
  • 这是一个bug report,您可以在 Powershell 的 UserVoice 上投票。

标签: powershell


【解决方案1】:

我意识到这个问题已经有几年的历史了,但由于它仍然是许多与通过资源管理器拖放运行 PowerShell 相关的谷歌查询的最佳结果,我想我会发布我想出的内容今天,希望它可以帮助其他人。

我希望能够将文件拖放到 PowerShell (ps1) 脚本上,但找不到任何好的解决方案(没有任何不涉及额外脚本或快捷方式的解决方案)。我开始在注册表中查找文件关联,并想出了一些似乎可以完美运行的东西。

首先,我们需要为 .PS1 文件添加 DropHandler 条目,以便资源管理器知道 PS1 文件应该接受拖放操作。使用此注册表更改来做到这一点。您可能必须创建 ShellEx 和 DropHandler 子键。

HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\ShellEx\DropHandler\
(Default) = {60254CA5-953B-11CF-8C96-00AA00B8708C}

此放置处理程序是 Windows Scripting Host 使用的处理程序。这是我的首选,因为它支持长文件名。如果遇到空格或其他问题,可以尝试标准的 Shell32 可执行文件(.exe、.bat 等)drop handler:{86C86720-42A0-1069-A2E8-08002B30309D}

这两个放置处理程序都通过简单地调用文件类型的默认谓词(双击文件时发生的情况)(被视为 Shell 键的 (Default) 值)来工作。对于 PS1 文件,这是打开。默认情况下,此动词在记事本中显示 PowerShell 脚本——不是很有帮助。

通过修改 PS1 文件的 Open 动词来更改此行为:

HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\Open\Command\
(Default) = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoExit -File "%1" %*

这将在打开时在 PowerShell 中运行脚本,并将所有参数(删除的文件)传递给它。我将它设置为在脚本完成后保持打开状态,但您可以通过删除 -NoExit 选项来更改它。

就是这样。我还没有进行任何广泛的测试,但到目前为止它似乎工作得很好。我可以删除单个文件/文件夹以及组。参数列表中文件的顺序并不总是您所期望的(Explorer 如何排序选定文件的一个怪癖),但除此之外它似乎很理想。您还可以在Shell:Sendto 中创建 PS1 文件的快捷方式,允许您使用“发送至”菜单传递文件。

以下是 REG 文件格式的两个变化:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\ShellEx\DropHandler]
@="{60254CA5-953B-11CF-8C96-00AA00B8708C}"

[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\Open\Command]
@="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" -NoExit -File \"%1\" %*"

注意事项:

  • 由于这些更改,在资源管理器中双击 PS1 文件将执行脚本;要编辑而不是打开,您必须使用右键菜单。并且作为一个建议(遗憾地从痛苦的经历中学到了:),如果您有执行破坏性操作的脚本,您可能会考虑使用确认/健全性检查守卫。

  • 通过拖放操作运行的脚本的默认起始工作目录为C:\Windows\system32\。另一个需要小心的原因。

  • 请记住,除非您使用签名脚本,否则您需要更改您的 Execution Policy (Set-ExecutionPolicy)。

  • 如果您在 Windows 10 上调整了对 .PS1 文件的处理,则需要删除注册表项 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.ps1\UserChoice,这将覆盖默认处理。

【讨论】:

  • 干得好!那肯定会奏效。我一直在使用 cmd.exe 批处理文件存根脚本,并且可能会继续。因为我需要确保任何人都可以完成这些任务,而不需要他们调整 PC 的默认 .PS1 处理。 ... 大一岁,保守一岁。
  • 在 Windows 8+ 上,确保将 Windows Registry Editor Version 5.00 添加为 .REG 文件的第一行
  • 如果有人在设置时遇到问题,我的fork of PS-SFTAMakePowerShellDnd.bat 中有一个脚本,它将为您将所有键添加到注册表并自动使其成为您的用户选择,因此它无需需要管理员权限。它在HKEY_CURRENT_USER\SOFTWARE\Classes而不是HKEY_CLASSES_ROOT下添加信息来支持这一点
【解决方案2】:

将文件或文件夹传递给 Powershell 脚本的最简单方法是如下所示的包装脚本:

@echo off
rem the name of the script is drive path name of the Parameter %0
rem (= the batch file) but with the extension ".ps1"
set PSScript=%~dpn0.ps1
set args=%1
:More
shift
if '%1'=='' goto Done
set args=%args%, %1
goto More
:Done
powershell.exe -NoExit -Command "& '%PSScript%' '%args%'"

你要做的就是

制作 .bat 文件的副本

将其命名为与脚本文件相同的名称,但扩展名为 .bat

例如“hello.ps1”“hello.bat”

将文件/文件夹拖放到批处理文件中,它会将它们传递给脚本。

示例脚本代码可能如下所示:

"hello world"
$args
$args.Gettype().Fullname

【讨论】:

  • 不是最简单的,但可能是微软修复我认为是错误的唯一方法。
  • 有什么理由不使用单线 powershell.exe -NoExit -Command "& '%~dpn0.ps1' %*" 而不是循环遍历参数吗?它不处理包含空格的路径,但据我所知,上述批处理脚本也没有。
  • @billyjmc 是的,但您可以使用set args='%~1'set args=%args%, '%~1' 调整@thomas-jüttner 的答案(并使用"& '%PSScript%' %args% " 调用powershell.exe)我认为
  • 不需要包装脚本。看看接受的答案...stackoverflow.com/a/45838761/80161
【解决方案3】:

自从公开以来,一直以来的秘密就是参数属性“ValueFromRemainingArguments”。

快捷方式、批处理或 CMD 文件来接收拖放的文件

5.1 或更早版本

powershell.exe -noexit -file c:\Test.ps1

Powershell 6 及更新版本

pwsh.exe -noexit -file c:\Test.ps1

Test.ps1

[CmdletBinding()]
param (
    [Parameter(ValueFromRemainingArguments=$true)]
    $Path
)

$Path

TestExpandDirectories.ps1

[CmdletBinding()]
param (
    [Parameter(ValueFromRemainingArguments=$true)]
    $Path
)

foreach ($aPath in $Path) {
    $aPath
    if (Test-Path $aPath -PathType Container) {
        Get-ChildItem $aPath -Recurse | Select-Object -ExpandProperty FullName
    }
}

此外,如果脚本没有参数块并且使用 Powershell -File ScriptName.ps1 运行,则 $args 变量将包含预期的内容,即文件路径数组。

【讨论】:

  • 结果应该是什么?它只是为我在 CMD 窗口中打开一个 powershell 提示符。甚至建议我尝试跨平台的 pcore6
  • Test.ps1 将简单地返回在运行它的快捷方式上放置的文件的路径。 TestExpandDirectories.ps1 添加了扩展在运行它的快捷方式上放置的任何目录的功能。 pscore 消息位于打开 Windows 本机版本 Powershell 时显示的标题中。如果这是您第一次运行 Powershell,请务必... Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
【解决方案4】:

将您的快捷方式更改为此并尝试:

powershell.exe -noprofile -noexit -command "& {c:\test1.ps1 $args}"

【讨论】:

  • 抱歉,这是一个优雅的答案,但不幸的是,路径被其中的任何空白分开。我已更新问题以反映此尝试。
  • 不,根据我的测试,$args 是一个字符串[]。您可能看到的是,如果将字符串数组呈现为字符串,PowerShell 会使用 $OFS 的值来分隔数组的每个条目。如果未设置 $OFS,则 PowerShell 使用空格作为分隔符。在您的脚本中,尝试设置$OFS = ', '
  • 是的 $args 是一个数组,但问题不是由数组扩展引起的。在快捷方式上拖动文件时,Windows 会传递由空格分隔的路径,并在必要时用引号括起来。您的快捷方式第二次传递文件,这次没有引号。脚本接收的是一个长字符串,然后通过在任何空白处拆分它来解析它。我喜欢您的想法,甚至尝试将参数 (@args) 分解,将它们包装为数组 (@($args)) 并将 $OFS 解决方案添加到命令行,但无济于事。如果你尝试一下,你就会明白我的意思。
  • 好的,我明白了。我正在使用没有空格的路径进行测试。这似乎是使用 -command 的限制。尝试使用此C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -noprofile -noexit -command "& {$args}" "a b" "c d" 的快捷方式。只需双击快捷方式(无需拖到它上面)。 PowerShell 以某种方式设法从参数中去除双引号。如果没有其他人想出答案,你应该在 MS Connect 上解决这个问题。
【解决方案5】:

将文件拖放到 PowerShell 脚本 --- 附加信息和解决方案

Nathan Hartley 使用快捷方式文件在上面发布的解决方案效果很好。 (见:stackoverflow.com/a/45838761/80161

事实证明,您可以轻松地使用 .BAT 文件,并获得相同的结果,使用其中任何一个来调用相同的底层 .ps1 脚本文件。

下面是这两种技术的总结。以下示例脚本已在 Windows 10 上使用 Windows PowerShell 5.1 (powershell.exe) 和 PowerShell 7.1 (pwsh.exe) 进行了测试。

文件和目录名称中的多个连续空格通过以下任一技术保留,这是上述其他一些解决方案的问题。 (Nathan 的解决方案在这方面效果很好。我在下面的摘要中包含了他的解决方案以及我的 .bat 文件解决方案。)

示例快捷方式文件:

在快捷方式的属性中输入如下内容作为“目标”:

powershell.exe -noexit -File "C:\Users\User\Documents\PS Scripts\your script.ps1"

假设 PowerShell 程序在您的路径中,您也可以在将上述内容输入快捷方式时简单地键入 powershell 或 pwsh。当您保存或应用快捷方式时,它会自动将名称扩展为完整的绝对文件名。此外,如果 -File 参数路径和文件名没有空格,则可以省略被调用的 .ps1 脚本名称周围的引号。

.BAT 文件示例:

@echo off
set PSScript=%~dpn0.ps1
powershell.exe -NoExit -File "%PSScript%" %*

与上述另一位作者的帖子一样,为 .BAT 文件提供与相应 PowerShell 脚本相同的基本名称。当然,如果您愿意,也可以将调用的脚本名称明确编码到 .BAT 文件中,但上述方法可以方便地将包装器和 .ps1 脚本作为一对移动。

"%PSScript%" 周围的引号很重要,但 %*(将传递给 .BAT 脚本的所有参数传递给 PowerShell 脚本)必须括在引号中。


以下示例 .ps1 脚本可以由上述任何一个调用:

选项 1:使用“ValueFromRemainingArguments”规范在“命名”参数中收集传递的路径名(这基本上是上面 Nathan 的示例):

param (
    [Parameter(ValueFromRemainingArguments=$true)]
    $Paths
)

'Paths:'
$Paths   # lists the dropped path names

选项 2:在 $Args 数组中提取参数:

# Simply reference the dropped path names in the $Args array.
# The following will list all the dropped path names.
# Yes, this is a one line .ps1 script!

$Args

以下演示了“选项 2”,其中添加了一些单独访问传递的路径名的简单代码:

$Args
''
'Example of accessing passed Args individually:'
write-host "=====There are a total of $($args.count) arguments:"
for ( $i = 0; $i -lt $args.count; $i++ ) {
    write-host "Argument  $i is $($args[$i])"
}

2021 年 6 月更新:请参阅下面的 follow-up post 了解增强的代码,这些代码也允许您包含和扩展已删除的目录。

10/2021 更新:使用 Windows 快捷方式或 .bat 文件方法通常效果很好。 但请注意以下权衡: .bat 文件非常容易为新脚本设置 - 只需复制以前的文件并将其命名为与新的 .ps1 脚本相同的基本名称.另一方面,我发现您可以在 Windows 快捷方式上放置更多文件。作为一个例子,我发现,在我的一个比较测试中,我可以在我的 .bat 文件上放置大约 90 个文件,在我的快捷方式上放置大约 380 个文件。当然,如果文件在一个目录中,并且您删除了目录名称,那么您就完全避免了这个限制。


关于上面共享的代码选项的说明:

  • Nathan 示例中显示的 [CmdletBinding()] 规范不是 必要的,并被覆盖 [ValueFromRemainingArguments=$true] 规范,这会导致所有 剩余的已删除文件名尚未被任何前面的文件拾取 要收集到命名 $Paths 参数中的参数 规格附后。

  • 当通过上面示例中的默认 $Args 变量访问已删除的文件名时,不得使用 [CmdletBinding()] 规范,否则您将收到错误,因为此规范要求所有传递的参数都具有匹配的参数规范.

  • 如果在 PowerShell 脚本中既没有指定“[CmdletBinding()]”也没有指定“[Parameter(ValueFromRemainingArguments=$true)]”,并且删除并传递给 PowerShell 脚本的文件多于命名参数,则文件名首先通过命名参数传递,其余的文件名作为 $Args 参数传递,以 $Args[0] 开头。

  • 上述解决方案中的一个关键元素是在调用相应 .ps1 脚本的 PowerShell 命令中使用 -File 参数而不是 -Command 参数。

  • 如上所述,pwsh.exe (PowerShell 7) 可用于代替快捷方式文件或批处理文件中的 powershell.exe (Windows PowerShell)。 p>

【讨论】:

    【解决方案6】:

    将文件拖放到 PowerShell 脚本中 --- 后续:扩展已删除的目录

    这是我上面帖子的后续内容:“Dragging and Dropping Files onto a PowerShell Script --- Additional Information and Solutions”。

    下面的 PowerShell 脚本可以与我之前发布的 .bat 文件或快捷方式文件技术一起使用,并为在 Windows 资源管理器中删除文件提供了额外的灵活性。该脚本也可以在 PowerShell 命令提示符下使用。

    • 这将允许删除目录和文件名的混合列表。目录将被扩展。

    • 从命令行手动运行时,还可以使用通配符指定文件(但不能指定目录)。

    • 任何传递的相对文件名都将转换为完全限定名,这对于某些应用程序可能很重要。

    param (
        [Parameter(ValueFromRemainingArguments=$true)]
        $DroppedFiles
    )
    
    if ( $DroppedFiles.count -eq 0 ) {
        Write-Host "Supply directory and/or file names. Wildcards are allowed." -ForegroundColor Red
        Exit
    }
    
    [bool]$err = $False
    foreach ($f in $DroppedFiles) {
        if ( ( [string]::IsNullOrWhiteSpace($f) ) -or ( (Test-Path -Path $f) -eq $False ) ) {
        Write-host "ERROR--File or directory does not exist: " -NoNewline  -ForegroundColor Red
        Write-host $f
        $err = $True
        }
    }
    if ( $err ) { Exit }
    
    $Droppedfiles = Get-ChildItem -Path $DroppedFiles -File -Depth 0 -Recurse -ErrorAction Stop
    
    $i = 0
    foreach ($File in $DroppedFiles) {
        Write-Host "Processing:" $File.FullName
        $i++
    }
    Write-Output "$i file(s) processed."
    

    注意事项:

    • 这将处理多个混合的目录和文件名。

    • 默认情况下,目录仅扩展至第一级(由“-Depth 0”设置)。您可以增加此限制或完全取消限制。

    • 您可以通过在 Get-ChildItem 行添加 -Include 参数来限制生成的文件列表,例如:-Include: *.doc,*.docx

    • 从命令行调用脚本时,指定的任何不存在的文件都不会返回任何内容(不报告错误),因此包括对不存在的文件或目录的初步检查。

    • 所编写的脚本可以很好地与 PowerShell 7.1 (pwsh.exe) 配合使用。

    • 更新 10/2021:我在 PowerShell 5.1 中发现了一个错误,该错误会在删除多级目录并同时使用 Include 参数时影响代码的操作。请参阅有关问题性质和可能解决方案的更多详细信息和 cmets,如果这对您来说是个问题,请在我的下一篇关于封装上述代码的“Test+Expand-Dropped-Files”函数的文章中。

    关于上述代码的其他 cmets:

    • 如果您的 PowerShell 脚本仅用于将文件从 Windows 资源管理器拖放到 .bat 文件或快捷方式文件中,如我上一篇文章中所述(而不是调用您的脚本并在命令行上传递参数),您应该能够省略两个初始测试块,因为 Windows 资源管理器将传递已知在您“删除”文件时存在的完全限定名称。如果您打算(或可能不小心)从命令行执行脚本,则附加测试会阻止 Get-ChildItem 在未提供参数的情况下默认获取当前目录中的所有文件,并确保任何用户键入的参数都执行存在。

    【讨论】:

      【解决方案7】:

      不幸的是,$args 会将您的参数拆分为空格,因此在包含它们的文件名上无法正常工作。但是,您仍然可以在 .ps1 中处理 $args 而无需外部包装脚本!

      由于您在快捷方式上拖放的所有内容(或选择“发送到”)都将作为空格连接的绝对路径列表传递给您的脚本,您可以使用 $args 解析所有出现的绝对路径正则表达式并将其通过管道传递给 foreach:

      $pattern = '([a-zA-Z]:\\(((?![<>:"/\\|?*]).)+((?<![ .])\\)?)*)(\s|$)'
      
      Select-String "$pattern" -input "$args" -AllMatches | Foreach {$_.matches} | ForEach-Object { 
          $path = "$($_.Groups.Groups[1].Value)"
          # ...
      } 
      

      每个$path 都是一个绝对路径(包括里面有空格的路径)

      绝对文件模式取自here

      我将它包裹在括号中(以匹配第一组与实际路径)并在末尾添加了一个 (\s|$) 组,即“空格或字符串结尾”,因为快捷方式参数将与单个空格连接; $ 需要匹配参数列表中的最后一个路径。

      【讨论】:

      • 问题在于 Powershell 如何在参数之间拆分删除的文件(它们的路径字符串),而不是将它们视为第一个参数的数组。如果您删除 param 块,$args 变量将包含您所期望的(除非您使用 Keith Hill 的 -command 解决方案),而无需使用正则表达式重新创建拆分。试试这个... TestScript.ps1: $args Shortcut: Powershell -File TestScript.ps1
      【解决方案8】:

      对于那些正在寻找一种快速且足够好的解决方案来将 single 文件拖放到需要字符串参数的 powershell 脚本的人,您可以使用它作为您的快捷方式:

      powershell.exe -noprofile -noexit -command "& {.\myscript.ps1 ($args -join ' ')}"
      

      如果您的文件路径包含多个连续空格,它可能会中断,但这对我来说效果很好,因为我从未遇到过需要使用这种技术的文件。

      【讨论】:

      • 尝试例外的答案。 stackoverflow.com/a/45838761/80161
      • 接受的答案很棒!它只是不太适合我不想修改被调用的脚本的情况。它不仅需要ValueFromRemainingArguments 参数标志,而且需要将参数类型从string 更改为object[]。也许添加新答案太小众了,但我能够避免破坏其他人正在使用的脚本的签名或维护仅限本地的更改。
      【解决方案9】:

      检查和扩展放置在 PowerShell 脚本上的文件名的功能

      为了简化我之前两篇文章的要点,但为了简化我希望能够在其上删除文件和目录的多个 PowerShell 脚本的创建,我创建了一个函数来执行检查和目录扩展。

      以下是我想出的:

      <#
      Function: Test+Expand-Dropped-Files
      Lewis Newton, 6/2021
      
      This function will process an intermixed list of directory and file names passed to a 
      PowerShell script when dropped in Windows Explorer on a properly configured accompanying
      Windows shortcut or .bat file.  The PowerShell script or .bat file can also be called directly
      from the command line.
      
      -- This function will accept multiple intermixed directory and file names.  
      -- It will check that the files exist, and expand any directories recursively to the depth
         specified (it defaults to 0, the top level).
      -- The 'Include' parameter allows limiting what is included, for example: -Include *.doc,*.docx
         It defaults to a $Null string array which will include everything found.  
      -- Relative file names and wildcard characters are accepted. 
      -- The function returns fully qualified file objects.
      -- Update 10/2021:  This works well with PowerShell 7.1.  I found a bug in PowerShell 5.1
         that affects operation when dropping multi-level directories if you supply an "-Include"
         parameter at the same time; the "-Depth 0" parameter is not honored in the "Get-ChildItem"
         command and you get results for any lower sub-directories as well. This is not
         an issue if you are not using "-Include", or if you only drop files or single level
         directories. See additional notes about possible solutions or workarounds (if this is an
         issue for you) toward the end of my web posting about this script on "stackoverflow".
      -- Note: "-Include $Null" (which is set as default) acts as if no parameter is present
         and in that case the "-Depth" parameter is honored in PowerShell 5.1 (this is not the
         case for "-Include '' ").
      #>
      
      function Test+Expand-Dropped-Files {
          param(
              $DroppedFiles,
              [string]$Depth = "0",
              [string[]]$Include = $Null
        )
      
      if ( $DroppedFiles.count -eq 0 ) {
          Write-Host "Supply directory and/or file names. Wildcards are allowed." -ForegroundColor Red
          Exit
          # Makes sure there is at least one parameter, or Get-ChildItem defaults to all in current directory.
          }
      
      [bool]$err = $False
      foreach ($f in $DroppedFiles) {
          if ( ( [string]::IsNullOrWhiteSpace($f) ) -or ( (Test-Path -Path $f) -eq $False ) ) {
          Write-host "ERROR--File or directory does not exist: " -NoNewline  -ForegroundColor Red
          Write-host $f
          $err = $True
          }
      }
      if ( $err ) { Exit }
      
      $Droppedfiles = Get-ChildItem -Path $DroppedFiles -File -Recurse -Depth $Depth -Include $Include -ErrorAction Stop
      # '-Depth 0' limits expansion of files in directories to the top level.
      # '-Include $Null' will include everything.
      
      Write-Output $DroppedFiles
      }
      

      为了在我的脚本中提供对函数的访问,我将上面的内容放在一个名为“function_Test+Expand-Dropped-Files.ps1”的文件中,然后从我的系统路径中的目录中点源。

      这是我在脚本开头放置的一个示例,用于调用该函数以方便拾取丢弃的文件和目录:

      param ( [Parameter(ValueFromRemainingArguments=$true)] $DroppedFiles )
      
      . function_Test+Expand-Dropped-Files
      $DroppedFiles = Test+Expand-Dropped-Files $DroppedFiles  -Depth 0 -Include $Null
      # '-Depth 0' limits directory expansion to first level.
      # '-Include' can specify a string array of specifications, such as: -Include *.doc,*.docx 
      # '-Depth' and '-Include' are optional and default to 0 and $Null (includes all) respectively.
      

      这是一个示例循环,显示了如何拾取和处理 $DroppedFiles 参数中传递的已删除文件名:

      $i = 0
      foreach ($File in $DroppedFiles) {
          Write-Host "Processing:" $File.FullName
          $i++
      }
      Write-Output "$i file(s) processed.`n"
      

      注意事项:

      • 现在您可以创建调用脚本的 .bat 文件或 Windows 快捷方式文件(如我之前的帖子中所述),您可以在 Windows 资源管理器中拖放文件和目录。当然,您也可以直接从 PowerShell 中调用 .ps1 脚本,在命令行中提供文件名(包括通配符)和目录名。

      • 上述函数的另一种替代方法是将“Test+Expand-Dropped-Files”函数放入您的 PowerShell 配置文件中,或将该函数设置为 PowerShell 模块。

      更新--2021 年 10 月:将其与 PowerShell 5.1 一起使用时发现的问题:

      (我还在上面函数的脚本代码中的 cmets 中添加了有关此问题的注释。)

      底线:如果您使用的是 PowerShell 7.1,则该功能可以正常工作。如果您使用的是 PowerShell 5.1,如果您传递给函数的任何目录名称中存在任何目录,该函数将递归到较低级别的目录,但前提是您使用“-Include”参数。如果这对您来说是个问题,请参阅下面的血腥细节以及处理此问题的一些建议。

      • 我发现“Get-ChildItem”的操作有一个错误(我 调用函数)与 PowerShell 5.1 一起使用时。 “递归” 当“-Include”时,选项需要下降到传递的目录 也可以使用,但如果您尝试限制深度(如“-Depth 0” 只是第一级),同时提供一个“-Include” 参数,深度被忽略,它在树中递归 PowerShell 5.1。请注意,在 PowerShell 7.1 中,“-Depth”参数 工作正常,深度限制在指定级别 这种情况。

      • 使用“-Filter”参数替代使用“-Include” 参数确实尊重深度参数,但在 从某种角度。我还注意到“-Filter *.doc”也会被选中 5.1 中的“.docx”文件,但 7.1 中没有。在 7.1 中,我可以使用“-Filter *.doc*” 来获取这两种类型的文件,但这也可能(虽然可能不太可能)更早地获取这样的字符串 在文件名中。

      • 关于上述任何一个版本的 PowerShell 的澄清说明, 如上所述,如果您将目录名称传递给“Get-ChildItem” 不使用“-Include”参数,并且不指定 “-Recurse”,然后在这种情况下,您将获得顶层文件 通过的目录。如果您使用“-Filter”也是如此。然而 当您使用“-Include”时,如上所述,您需要 “-Recurse”和“-Depth 0”获取顶层文件。

      • 另一种创建函数的选项 PowerShell 版本将使用“Get-ChildItem”而不 “-Include”,以便尊重“-Depth”参数,然后 明确跟进一个简单的代码循环来提取您的文件 想要加入。

      • 只要我使用 PowerShell 7.1,我就可以很好地使用它的功能, 我的功能按预期工作。也许在某些时候错误 PowerShell 5.1 将被修复。

      • 总结:这只是 PowerShell 5.1 的问题,不是 如果您没有使用“-Include”,或者您只删除文件,则会出现问题 或单级目录。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-12
        • 1970-01-01
        • 2020-03-12
        • 2015-11-10
        相关资源
        最近更新 更多