在Powershell中,Get-ChildItem的结果看起来像是相对路径。

4

我想使用 Powershell 扫描并将文件夹(包括子文件夹甚至更深层次的文件夹)从一个文件夹移动到另一个文件夹。

目前,我正在使用以下命令管道。

Get-ChildItem  -recurse  -path sub\WORK  -filter "* OK" | Where-Object { $_.PSIsContainer } | foreach { Move-Item -path $_  -destination sub\OK }

很不幸,它不能正常工作,因为找到的结果是相对于.\sub\WORK的,当尝试移动它们时,Move-Item会抱怨这些文件夹不在当前文件夹中:

Move-Item : Cannot find path 'C:\TMP\2011-12-12 test 2 OK' because it does not exist.

我希望$_包含:'C:\TMP\sub\WORK\2011-12-12 test 2 OK',因为这些是PowerShell中的对象,而不是像Linux中的字符串。

4个回答

5

如果你使用 Get-ChildItem,要非常小心。最好的方法是将对象管道传输到 Move-Item,这样就不需要再考虑它了:

Get-ChildItem  -recurse  -path sub\WORK  -filter "* OK" | Where-Object { $_.PSIsContainer } | Move-Item -destination sub\OK

不需要使用 Foreach-Object

我回答的主要原因是这个:根据参数不同,Get-ChildItem 构造对象的方式也不同。看看下面的例子:

PS C:\prgs\tools\Console2> gci -include * | % { "$_" } | select -fir 5
C:\prgs\tools\Console2\-verbose
C:\prgs\tools\Console2\1UpdateDataRepositoryServices.ps1
C:\prgs\tools\Console2\22-52-59.10o52l
C:\prgs\tools\Console2\2jvcelis.ps1
C:\prgs\tools\Console2\a
PS C:\prgs\tools\Console2> gci | % { "$_" } | select -fir 5
-verbose
1UpdateDataRepositoryServices.ps1
22-52-59.10o52l
2jvcelis.ps1
a

如果您在循环中使用 $_,并且PowerShell需要将 Get-ChildItemFileInfo 转换为字符串,则会得到不同的结果。当您将 $_ 用作 Move-Item 的参数时,就会发生这种情况。相当糟糕。

我认为这是一个报告该行为的错误。


对我来说,它看起来像是一个 bug,但我的 PowerShell 经验不够丰富,无法像那样指出问题。如果我在 'Get-ChildItem' 中添加 '-include "* OK" ',它也可以正常工作。你的解释非常有帮助。 - Paul Pladijs
好吧,你不应该依赖于ToString(),除非那是你唯一拥有的。 :) - JasonMArcher

3
您说得没错,对象被传递到管道中而不是字符串。这样做的好处在于它更加灵活。缺点是,如果您没有明确告诉系统要使用对象的哪个属性,那么您就会受制于系统设计者。尝试明确告诉系统您想要使用的属性是否有帮助:
Get-ChildItem  -recurse  -path sub\WORK  -filter "* OK" | Where-Object { $_.PSIsContainer } | foreach { Move-Item -path $_.Fullname  -destination sub\OK }

2

我刚刚学到,当你在管道中不指定源时,PSPath会自动在Copy-Item、Move-Item等命令中使用。因此,类似以下的命令:

gci .\sub\Work | move-item -Destination .\sub\OK

(简化示例)

这将起作用,并且它将使用传递对象的PSPath来确定源。


由于Get-ChildItem返回对象,因此您可以使用Get-Member查看对象提供了什么(也就是了解其属性和方法)。

 Get-ChileItem path | Get-Member

您可以看到FullName是其中一个可用的属性。


0

这是对我有效的方法。

Get-ChildItem -Path .\ -Recurse -filter "* OK" | %{Join-Path -Path $_.Directory -ChildPath $_.Name } | Move-Item -Destination sub\OK

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接