我想使用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中那样的字符串。
答案 0 :(得分:4)
如果您使用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需要将FileInfo
从Get-ChildItem
转换为字符串,则会产生不同的结果。当您使用$_
作为Move-Item
的参数时发生这种情况。非常糟糕。
我认为存在报告此行为的错误。
答案 1 :(得分:3)
你说对象是管道而不是字符串。这很好,因为它更灵活。缺点是,如果您没有明确告诉系统要使用的对象属性,那么您将受系统设计人员的支配。看看是否明确告诉系统您想要的属性将有所帮助:
Get-ChildItem -recurse -path sub\WORK -filter "* OK" | Where-Object { $_.PSIsContainer } | foreach { Move-Item -path $_.Fullname -destination sub\OK }
答案 2 :(得分:1)
我只是不知道当你没有在管道中指定源时,PSPath
会自动用在Copy-Item,Move-Item等中,所以类似于:
gci .\sub\Work | move-item -Destination .\sub\OK
(简化示例)
可以工作,它将使用传递对象的PSPath
来确定源。
由于Get-ChildItem
返回了你所说的对象,你可以使用Get-Member
来查看对象提供的内容(了解其属性和方法)
Get-ChileItem path | Get-Member
您可以看到FullName是您可以使用的属性之一。
答案 3 :(得分:0)
这对我有用。
Get-ChildItem -Path .\ -Recurse -filter "* OK" | %{Join-Path -Path $_.Directory -ChildPath $_.Name } | Move-Item -Destination sub\OK