如何使用 PowerShell 一次移动多个项目?
How do you move more than a single item with PowerShell at once?
当我尝试 运行:
mv test.txt test2.txt test-files
Returns错误:
Move-Item : A positional parameter cannot be found that accepts argument '.\test-files\'.
At line:1 char:1
+ mv .\test.txt .\test2.txt .\test-files\
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Move-Item], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.MoveItemCommand
但是,如果我只是一次移动一个文件
mv test.txt test-files
mv test2.txt test-files
然后它移动文件,但如果我有两个以上的文件,这似乎很乏味。
有什么方法可以同时将多个文件移动到特定位置吗?
我试过 mv t*.txt test-files 有效,但我实际要移动的文件是 index.html 和 style.css
注意:如您的错误消息所示,mv
是 PowerShell Move-Item
cmdlet 的 built-in 别名(尽管仅在 Windows 上)- 请参阅底部部分为什么这是有问题的,为什么最好使用 mi
别名。
在评论中提供了关键指针:
多个源路径必须作为数组传递给Move-Item
的-Path
或-LiteralPath
参数,直接指定路径 需要用 ,
:
分隔它们
# Note the "," separating the source file names.
Move-Item -LiteralPath test.txt, test2.txt -Destination test-files
我在上面使用了 named 参数,即我在参数前面加上了它们的目标参数的名称。
PowerShell 还支持位置 参数绑定:
Move-Item test.txt, test2.txt test-files
这行得通,但请注意,它并不完全等同于上面的方法,因为第一个位置参数 - test.txt, test2.txt
绑定到 -Path
参数,而不是 -LiteralPath
:
- 这里没有区别,因为手头的文件名不包含 wildcard 个字符。
- 但是,如果您的文字文件名恰好包含
[
(例如,test[2].txt
),绑定到 -Path
将无法按预期工作。
发现 cmdlet 的参数是否支持数组:
您可以通过查看其 syntax diagrams 来确定给定参数是否支持数组,这些是您传递 [= 时显示的简短帮助的一部分168=]标准-?
开关;例如,您也可以使用 Get-Command -Syntax Move-Item
单独显示它们。
使用Get-Help
,您甚至可以询问有关特定参数的详细信息,以-Path
为例:
PS> Get-Help Move-Item -Parameter Path
-Path <System.String[]>
Specifies the path to the current location of the items. The default is the current directory. Wildcard characters are permitted.
Required? true
Position? 0
Default value Current directory
Accept pipeline input? True (ByPropertyName, ByValue)
Accept wildcard characters? true
<System.String[]>
表示参数的类型,在本例中是一个数组 ([]
of System.String
([string]
) 个实例。换句话说:[]
后面的参数类型表示支持数组。
但是,给定的 cmdlet 可以选择 也 支持将多个参数单独传递给array-typed 参数(每个 cmdlet 必须只有 一个 参数可以支持此参数),使用 [Parameter()]
属性声明,其 ValueFromRemainingArguments
属性设置为 $true
:
一个例子是 Write-Output
,它的(唯一的位置)-InputObject
参数被键入 System.Management.Automation.PSObject[]
,但也有 ValueFromRemainingArguments
集,所以下面两个呼叫是等价的:[1]
# Single array argument that directly binds to -InputObject
Write-Output 1, 2, 3
# Multiple arguments that implicitly bind collected in an array to -InputObject
Write-Output 1 2 3
注:
不幸的是,帮助没有揭示ValueFromRemainingArguments
的存在——既不在参数的Get-Help ... -Parameter ...
的详细视图,通常也不在参数描述中。
虽然 程序化发现是可能的,但它并不平凡:
# -> 'InputObject'
(Get-Command Write-Output).Parameters.Values.
Where({ $_.Attributes.ValueFromRemainingArguments -contains $true }).Name
另一个示例是 Write-Host
,其 -Object
参数的行为方式相同。然而,这个参数的不寻常之处在于它的类型是 -Object <System.Object>
,即它没有明确表明它接受 arrays;但是,确实如此;从技术上讲,这可能是因为 System.Object
能够存储 任何 数据类型,包括数组(集合)。只有参数 描述 中的复数形式暗示 -Object
接受数组:“要在主机中显示的对象。”
Alias-naming 考虑因素:
mv
是 Move-Item
的 built-in 别名(仅在 Windows 上)[2] 是有问题的。更广泛地说,所有以 不同 shell 的内部命令命名的别名(例如,cmd.exe
的 dir
) 或者,在这种情况下,对于外部程序(可能是不同的平台)有问题, 因为这些命令/程序的语法通常与 PowerShell 的语法根本不同。
- 恰当的例子:您问题中的
mv
命令 将 与 Unix-platform /bin/mv
实用程序一起使用。
最好使用 PowerShell 自己的 别名,其名称是从命令的 approved verb 部分有条不紊地形成的别名,每个批准的动词都有其官方缩写,例如 m
代表 Move-
。 名词部分的缩写没有标准化,但使用首字母是有道理的,例如i
对于 Item
.
- 在PowerShell (Core) 7+中,您可以通过
Get-Verb
(输出列AliasPrefix
)发现动词缩写,例如Get-Verb Move
;在 Windows PowerShell 中,您需要参考上面的“批准动词”link。
而且,事实上,mi
是 Move-Item
的另一个 built-in 别名,因为以下基于 Get-Alias
的发现命令显示:
PS> Get-Alias -Definition Move-Item
CommandType Name Version Source
----------- ---- ------- ------
Alias mi -> Move-Item
Alias move -> Move-Item
Alias mv -> Move-Item # WINDOWS ONLY
这种别名的一大优势——除了不假装是他们不是的东西——是他们有条不紊的命名使它更容易记住和 p甚至可以猜出他们的名字;例如,gc
代表 Get-Content
,正如 Get-Alias -Definition Get-Alias
所揭示的,gal
代表 Get-Alias
.
与外部程序的名称冲突仍然可能发生,但可能性较小。例如。 sc
for Set-Content
隐藏了本机 sc.exe
实用程序(用于控制服务),这就是它被从 PowerShell (Core) 中删除的原因 - 有点争议 -
[1] 由于 GitHub 问题 #5122 中描述的错误,如果您还使用 Write-Output
在 PowerShell (Core) 7+ 中的 -NoEnumerate
开关,尽管在实践中差异很少重要:Write-Output -NoEnumerate 1, 2, 3
发出单个 [object[]]
实例,正如预期的那样,而 Write-Output -NoEnumerate 1 2 3
意外输出一个 [System.Collections.Generic[object]]
实例。在 Windows PowerShell 中,有一个不同的、更严重的错误:只有形式 Write-Output -NoEnumerate 1, 2, 3
产生一个 [object[]]
数组作为单个输出对象,如预期的;相比之下,形式 Write-Output -NoEnumerate 1 2 3
甚至 Write-Output -NoEnumerate -InputObject 1, 2, 3
有效地 忽略 -NoEnumerate
开关,因此一个一个地输出元素。
[2] 在 Unix-like 平台上,mv
别名未定义,以免影响外部,platform-native /bin/mv
程序.
当我尝试 运行:
mv test.txt test2.txt test-files
Returns错误:
Move-Item : A positional parameter cannot be found that accepts argument '.\test-files\'.
At line:1 char:1
+ mv .\test.txt .\test2.txt .\test-files\
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Move-Item], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.MoveItemCommand
但是,如果我只是一次移动一个文件
mv test.txt test-files
mv test2.txt test-files
然后它移动文件,但如果我有两个以上的文件,这似乎很乏味。
有什么方法可以同时将多个文件移动到特定位置吗?
我试过 mv t*.txt test-files 有效,但我实际要移动的文件是 index.html 和 style.css
注意:如您的错误消息所示,mv
是 PowerShell Move-Item
cmdlet 的 built-in 别名(尽管仅在 Windows 上)- 请参阅底部部分为什么这是有问题的,为什么最好使用 mi
别名。
多个源路径必须作为数组传递给Move-Item
的-Path
或-LiteralPath
参数,直接指定路径 需要用 ,
:
# Note the "," separating the source file names.
Move-Item -LiteralPath test.txt, test2.txt -Destination test-files
我在上面使用了 named 参数,即我在参数前面加上了它们的目标参数的名称。
PowerShell 还支持位置 参数绑定:
Move-Item test.txt, test2.txt test-files
这行得通,但请注意,它并不完全等同于上面的方法,因为第一个位置参数 - test.txt, test2.txt
绑定到 -Path
参数,而不是 -LiteralPath
:
- 这里没有区别,因为手头的文件名不包含 wildcard 个字符。
- 但是,如果您的文字文件名恰好包含
[
(例如,test[2].txt
),绑定到-Path
将无法按预期工作。
发现 cmdlet 的参数是否支持数组:
您可以通过查看其 syntax diagrams 来确定给定参数是否支持数组,这些是您传递 [= 时显示的简短帮助的一部分168=]标准-?
开关;例如,您也可以使用 Get-Command -Syntax Move-Item
单独显示它们。
使用Get-Help
,您甚至可以询问有关特定参数的详细信息,以-Path
为例:
PS> Get-Help Move-Item -Parameter Path
-Path <System.String[]>
Specifies the path to the current location of the items. The default is the current directory. Wildcard characters are permitted.
Required? true
Position? 0
Default value Current directory
Accept pipeline input? True (ByPropertyName, ByValue)
Accept wildcard characters? true
<System.String[]>
表示参数的类型,在本例中是一个数组 ([]
of System.String
([string]
) 个实例。换句话说:[]
后面的参数类型表示支持数组。
但是,给定的 cmdlet 可以选择 也 支持将多个参数单独传递给array-typed 参数(每个 cmdlet 必须只有 一个 参数可以支持此参数),使用 [Parameter()]
属性声明,其 ValueFromRemainingArguments
属性设置为 $true
:
一个例子是 Write-Output
,它的(唯一的位置)-InputObject
参数被键入 System.Management.Automation.PSObject[]
,但也有 ValueFromRemainingArguments
集,所以下面两个呼叫是等价的:[1]
# Single array argument that directly binds to -InputObject
Write-Output 1, 2, 3
# Multiple arguments that implicitly bind collected in an array to -InputObject
Write-Output 1 2 3
注:
不幸的是,帮助没有揭示
ValueFromRemainingArguments
的存在——既不在参数的Get-Help ... -Parameter ...
的详细视图,通常也不在参数描述中。虽然 程序化发现是可能的,但它并不平凡:
# -> 'InputObject' (Get-Command Write-Output).Parameters.Values. Where({ $_.Attributes.ValueFromRemainingArguments -contains $true }).Name
另一个示例是 Write-Host
,其 -Object
参数的行为方式相同。然而,这个参数的不寻常之处在于它的类型是 -Object <System.Object>
,即它没有明确表明它接受 arrays;但是,确实如此;从技术上讲,这可能是因为 System.Object
能够存储 任何 数据类型,包括数组(集合)。只有参数 描述 中的复数形式暗示 -Object
接受数组:“要在主机中显示的对象。”
Alias-naming 考虑因素:
mv
是 Move-Item
的 built-in 别名(仅在 Windows 上)[2] 是有问题的。更广泛地说,所有以 不同 shell 的内部命令命名的别名(例如,cmd.exe
的 dir
) 或者,在这种情况下,对于外部程序(可能是不同的平台)有问题, 因为这些命令/程序的语法通常与 PowerShell 的语法根本不同。
- 恰当的例子:您问题中的
mv
命令 将 与 Unix-platform/bin/mv
实用程序一起使用。
最好使用 PowerShell 自己的 别名,其名称是从命令的 approved verb 部分有条不紊地形成的别名,每个批准的动词都有其官方缩写,例如 m
代表 Move-
。 名词部分的缩写没有标准化,但使用首字母是有道理的,例如i
对于 Item
.
- 在PowerShell (Core) 7+中,您可以通过
Get-Verb
(输出列AliasPrefix
)发现动词缩写,例如Get-Verb Move
;在 Windows PowerShell 中,您需要参考上面的“批准动词”link。
而且,事实上,mi
是 Move-Item
的另一个 built-in 别名,因为以下基于 Get-Alias
的发现命令显示:
PS> Get-Alias -Definition Move-Item
CommandType Name Version Source
----------- ---- ------- ------
Alias mi -> Move-Item
Alias move -> Move-Item
Alias mv -> Move-Item # WINDOWS ONLY
这种别名的一大优势——除了不假装是他们不是的东西——是他们有条不紊的命名使它更容易记住和 p甚至可以猜出他们的名字;例如,
gc
代表Get-Content
,正如Get-Alias -Definition Get-Alias
所揭示的,gal
代表Get-Alias
.与外部程序的名称冲突仍然可能发生,但可能性较小。例如。
sc
forSet-Content
隐藏了本机sc.exe
实用程序(用于控制服务),这就是它被从 PowerShell (Core) 中删除的原因 - 有点争议 -
[1] 由于 GitHub 问题 #5122 中描述的错误,如果您还使用 Write-Output
在 PowerShell (Core) 7+ 中的 -NoEnumerate
开关,尽管在实践中差异很少重要:Write-Output -NoEnumerate 1, 2, 3
发出单个 [object[]]
实例,正如预期的那样,而 Write-Output -NoEnumerate 1 2 3
意外输出一个 [System.Collections.Generic[object]]
实例。在 Windows PowerShell 中,有一个不同的、更严重的错误:只有形式 Write-Output -NoEnumerate 1, 2, 3
产生一个 [object[]]
数组作为单个输出对象,如预期的;相比之下,形式 Write-Output -NoEnumerate 1 2 3
甚至 Write-Output -NoEnumerate -InputObject 1, 2, 3
有效地 忽略 -NoEnumerate
开关,因此一个一个地输出元素。
[2] 在 Unix-like 平台上,mv
别名未定义,以免影响外部,platform-native /bin/mv
程序.