简体   繁体   English

Powershell删除项%1(上下文菜单)

[英]Powershell Remove-Item %1 (Context Menu)

Been fighting with Powershell to do what I need it to do. 一直在与Powershell战斗以完成我需要做的事情。 It might be a simple solution but I've not found it. 这可能是一个简单的解决方案,但我没有找到它。 If this question is a duplicate, I do apologize, but I couldn't find the answer I was looking for. 如果这个问题重复,我会道歉,但是找不到我想要的答案。

TL;DR at the bottom. TL; DR在底部。

So, to the issue I have. 所以,对于我的问题。 I'm trying to add a PS script to context menu via regedit that deletes a folder + files within, it works great on folders without any spaces in it but when I try to delete a folder with spaces (like "New Folder") it throws an error and closes. 我正在尝试通过regedit将PS脚本添加到上下文菜单中,该脚本删除其中的文件夹+文件,它在其中没有任何空格的文件夹上效果很好,但是当我尝试删除有空格的文件夹(例如“ New Folder”)时,引发错误并关闭。 (Tried looking for a pause / sleep command with Remove-Item but no luck, except for long scripts with error handling etc.) (试图通过Remove-Item查找暂停/睡眠命令,但是运气不好,除了长脚本有错误处理等)。

I suspect the error is similar to 我怀疑错误类似于

Remove-Item : A positional parameter cannot be found that accepts argument 'Folder'.

At line:1 char:12 + Remove-item <<<< New Folder + CategoryInfo : InvalidArgument: (:) [Remove-Item], ParameterBindingException + FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand 在第1行:char:12 +删除项<<<<新文件夹+ CategoryInfo:InvalidArgument:(:) [Remove-Item],ParameterBindingException + FullyQualifiedErrorId:PositionalParameterNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand

And the code I'm currently using is 我当前使用的代码是

cmd /c  PowerShell Remove-Item "%1" -recurse -force

I've tried different variations for it to work without luck. 我尝试了各种变体,使其无法正常运行。 IE replacing "%1" with "pathAsString", added another "% 1" , added wildcard "* *" , removed the flags. IE将"%1"替换为“ pathAsString”,添加了另一个"% 1" ,添加了通配符"* *" ,并删除了这些标志。 Some different variations on the code I've tried: 我尝试过的代码有一些不同的变化:

cmd /c PowerShell Remove-Item \"%1\" -recurse -force
cmd /c PowerShell Remove-Item & "{"%1" -recurse -force"}"

TL;DR cmd /c PowerShell Remove-Item "%1" -recurse -force ignores folders with white spaces, tried various things. TL; DR cmd /c PowerShell Remove-Item "%1" -recurse -force忽略带有空格的文件夹,并尝试了各种操作。 Usage in Context Menu (via Regedit). 上下文菜单中的用法(通过Regedit)。

Might be a solution that's obvious but I don't see it. 可能是一个显而易见的解决方案,但我没有看到。

The following worked for me: 以下为我工作:

cmd /c PowerShell -command "& {Remove-Item -path '%1' -recurse -force -confirm:$false}"

When using cmd.exe, there is no such thing as a script block. 使用cmd.exe时,没有脚本块之类的东西。 This means the value passed to -command will always be a string. 这意味着传递给-command的值将始终是字符串。 I added the single quotes ('') around %1 to keep your double quotes ("") with your argument. 我在%1周围添加了单引号('') ,以将双引号("")与参数一起使用。 Apparently, this method will fail if you have a single quote (') in your file path. 显然,如果文件路径中带有单引号(') ,则此方法将失败。 Also the call operator & is not required even though the online documentation says it is. 此外,即使在线文档中说明了,也不需要呼叫运营商&

See PowerShell.exe Command-Line Help for more information on how to use PowerShell.exe . 有关如何使用PowerShell.exe更多信息,请参见PowerShell.exe命令行帮助

See About Quoting Rules for more information on how PowerShell single and double quotation marks work. 有关PowerShell单引号和双引号如何工作的更多信息,请参见关于报价规则

One of your attempts: 您的尝试之一:

cmd /c PowerShell Remove-Item \\"%1\\" -recurse -force

actually does work, albeit only if those paths that have embedded spaces don't contain multiple adjacent spaces (see the bottom section for why your first attempt with "%1" instead of \\"%1\\" didn't work). 确实有效,尽管只有那些具有嵌入式空格的路径不包含多个相邻空格(请参阅底部,了解为什么您第一次尝试使用"%1"而不是\\"%1\\"无效)。

To make the command robust (and also more efficient), use the following variation, which does not involve cmd.exe (because it isn't necessary), and the command to pass to PowerShell is enclosed in "..." as a whole with embedded " escaped as \\" (as in your attempt): 为了使命令强劲 (也更有效),使用下面的变化,这涉及cmd.exe (因为它是没有必要的),并命令传递给PowerShell是封闭在"..." 作为整体带有嵌入的"转义为\\" (如您的尝试):

powershell.exe -noprofile -command "Remove-Item -LiteralPath \"%1\" -Recurse -Force"

PowerShell CLI options used: 使用的PowerShell CLI选项:

  • -noprofile suppresses loading of the current user's profile ( $PROFILE ), which would only unnecessarily slow down the command (or, worse, could change its behavior). -noprofile禁止加载当前用户的配置文件( $PROFILE ),这只会不必要地减慢该命令的速度(或者更糟的是,可以更改其行为)。

  • -command tells PowerShell that the remaining arguments are a PowerShell command (a piece of source code, as distinct from -file , which is used to invoke a script ) -command告诉PowerShell其余参数是PowerShell命令(一段源代码,与-file不同,后者用于调用脚本

    • While you don't strictly need to specify -command in Windows PowerShell, because it is implied , that is no longer the case in PowerShell Core , which defaults to -file . 尽管您不必严格要求在Windows PowerShell中指定-command ,因为它隐含了该内容,但在PowerShell Core中已不再是这种情况,默认情况下,该属性为-file

The Remove-Item command passed to PowerShell: 传递给PowerShell的Remove-Item命令:

  • Enclosing the entire PowerShell command in "..." ensures that whitespace inside the command is preserved as-is , which matters with paths that happen to contain runs of multiple spaces, eg "c:\\Users\\jdoe\\Invoices<space><space>2018" 整个 PowerShell命令括在"..."可确保命令内的空格按原样保留 ,这与碰巧包含多个空格的运行路径有关,例如"c:\\Users\\jdoe\\Invoices<space><space>2018"

  • \\" is how PowerShell requires nested (embedded) " chars. \\"是PowerShell如何需要嵌套 (嵌入) "字符。 with to be escaped when called from the command line with -command - see below for an explanation. 使用-command 从命令行调用时 ,可以使用-进行转义 -有关说明,请参见下文。

  • -LiteralPath ensures that Remove-Item interprets the path literally rather than as a wildcard pattern (as would happen by default, with the implied -Path parameter); -LiteralPath确保Remove-Item字面方式解释路径,而不是将其解释为通配符模式 (默认情况下会使用隐含的-Path参数); while not very likely, paths such as c:\\tmp\\folder[] would break the command if taken as a wildcard. 虽然不太可能,但是如果将c:\\tmp\\folder[]这样的路径用作通配符,则会破坏该命令。

Caveats : 注意事项

  • Due to (ultimately) using double quotes ( "..." ) to enclose the path (the directory path that File Explorer expands %1 to), it becomes an expandable string , ie, it is subject to string interpolation , which means that folder paths that contain $ characters (eg, c:\\tmp\\$foo ) could be misinterpreted. 由于(最终)使用双引号( "..." )括住路径(文件资源管理器将%1扩展到的目录路径),因此它变成了可扩展的字符串 ,即受到字符串插值的影响 ,这意味着包含$字符的文件夹路径(例如c:\\tmp\\$foo )可能会被误解。

  • You can suppress this interpolation by replacing \\"%1\\" with '%1' , ie, by using a single-quoted string (which PowerShell always treats literally), but the problem is that you then won't be able to use the command on folders whose paths happen to have ' chars. 您可以通过将\\"%1\\"替换为'%1'来抑制这种插值,即使用单引号引起来的字符串(PowerShell始终按字面意义对待),但是问题是您将无法使用路径碰巧带有'字符的文件夹上的命令。 in them (eg, c:\\tmp\\o'reilly ) 在它们中(例如c:\\tmp\\o'reilly


Why just "%1" isn't enough: 为什么仅使用"%1"还不够:

cmd /c PowerShell Remove-Item "%1" -recurse -force , your (first) command line (which you're using as a command definition for File Explorer's context menus ), is processed as follows: cmd /c PowerShell Remove-Item "%1" -recurse -force (您的(第一条)命令行(您将其用作File Explorer上下文菜单命令定义 ))的处理如下:

  • File Explorer replaces %1 with the absolute path of the file for folder that was right-clicked, as-is - whether or not the path has embedded spaces; “文件资源管理器”按原样-用右键单击的文件夹的文件绝对路径替换%1路径是否包含嵌入的空格; eg: 例如:

    • c:\\Users\\jdoe\\Invoices 2018 . c:\\Users\\jdoe\\Invoices 2018
  • The resulting command line is then executed; 然后执行结果命令行; eg: 例如:

    • cmd /c PowerShell Remove-Item "c:\\Users\\jdoe\\Invoices 2018" -recurse -force
  • cmd /c is incidental here (and not needed): It essentially just relays the command line to PowerShell (via its executable, powershell.exe ); cmd /c在这里是偶然的(不需要):它实际上只是将命令行中继到PowerShell(通过其可执行文件powershell.exe ); eg: 例如:

    • powershell.exe Remove-Item "c:\\Users\\jdoe\\Invoices 2018" -recurse -force
  • PowerShell first processes the individual arguments - Remove-Item , "c:\\Users\\jdoe\\Invoices 2018" , -recurse , -force by removing enclosing double quotes . PowerShell 首先通过删除双引号来处理各个参数Remove-Item"c:\\Users\\jdoe\\Invoices 2018"-recurse-force

  • Since the -command option is implied, the quote-stripped arguments are re-joined with a space as the separator and then interpreted as a snippet of PowerShell source code ; 由于隐含了-command选项,因此将使用引号分隔的参数重新连接,并使用空格作为分隔符, 然后将其解释为PowerShell源代码片段 eg: 例如:

    • Remove-Item c:\\Users\\jdoe\\Invoices 2018 -recurse -force

    • As you can see, the removal of the double quotes resulted in a broken PowerShell command, because the path with spaces now lacks quoting so that c:\\Users\\jdoe\\Invoices 2018 is no longer recognized as a single argument and is instead interpreted as 2 arguments, prefix c:\\Users\\jdoe\\Invoices followed by 2018 as its own, syntactically extraneous argument. 如您所见,双引号的删除导致PowerShell命令损坏,因为带有空格的路径现在缺少引号,因此c:\\Users\\jdoe\\Invoices 2018不再被视为单个参数,而是被解释为2个参数,前缀c:\\Users\\jdoe\\Invoices后跟2018作为语法上无关的参数。

    • While using \\"%1\\" instead of "%1" alone would prevent the up-front quote stripping - by telling PowerShell that the " chars. are to be retained during initial argument parsing - additionally enclosing the entire PowerShell command in "..." is necessary to correctly preserve file paths with multiple adjacent spaces (even though such paths may be the result of a typo during folder creation): 当使用\\"%1\\" ,而不是"%1"单独将阻止的前期报价剥离-告诉PowerShell中,所述"字符是初始参数解析过程中要保留 - 。另外包围在整个PowerShell命令 "..."对于正确保留多个相邻空间的文件路径是必要的(即使这些路径可能是文件夹创建过程中输入错误的结果):

      • Without overall enclosing "..." , a \\" -quoted path such as C:\\Users\\jdoe\\Invoices<space><space>2018 would result in the following 2 arguments: 如果不整体包含"..." ,则使用\\"引号的路径(例如C:\\Users\\jdoe\\Invoices<space><space>2018将导致以下两个参数:

        • \\"C:\\Users\\jdoe\\Invoices
        • 2018\\"
        • When PowerShell later re-joins the individual arguments with a single space between them (after having recognized \\" as an escaped " to be retained ), before interpreting the resulting string as PowerShell code, it sees "C:\\Users\\jdoe\\Invoices<space>2018" , ie, only a single space. 当PowerShell稍后在各个参数之间用单个空格重新连接时(在将\\"识别为要保留转义" ), 将结果字符串解释为PowerShell代码之前,它将看到"C:\\Users\\jdoe\\Invoices<space>2018" ,即,仅一个单一的空间。
      • With overall enclosing "..." , the entire PowerShell command is parsed as a single argument, with interior whitespace preserved as-is , which avoids the problem. 随着整体封闭"..." ,整个PowerShell命令被解析为一个单独的参数,与室内空白保留原样 ,避免了这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM