我基本上要到运行:
C:\>xcopy [0-9]{13}\.(gif|jpg|png) s:\TargetFolder /s
我知道xcopy
不支持正则表达式文件名搜索。
我不知道如何找出PowerShell是否具有Cmdlet
复制文件;以及是否支持正则表达式文件名匹配。
谁能想到一种使用正则表达式文件名匹配来执行递归文件复制/移动的方法吗?
我基本上要到运行:
C:\>xcopy [0-9]{13}\.(gif|jpg|png) s:\TargetFolder /s
我知道xcopy
不支持正则表达式文件名搜索。
我不知道如何找出PowerShell是否具有Cmdlet
复制文件;以及是否支持正则表达式文件名匹配。
谁能想到一种使用正则表达式文件名匹配来执行递归文件复制/移动的方法吗?
Answers:
我喜欢在可能的情况下使用所有Powershell命令。经过一点测试,这是我能做的最好的。
$source = "C:\test"
$destination = "C:\test2"
$filter = [regex] "^[0-9]{6}\.(jpg|gif)"
$bin = Get-ChildItem -Path $source | Where-Object {$_.Name -match $filter}
foreach ($item in $bin) {Copy-Item -Path $item.FullName -Destination $destination}
前三行只是为了使它更易于阅读,您可以根据需要在实际命令中定义变量。此代码示例的关键是“ Where-Object”命令,该命令是一个接受正则表达式匹配的过滤器。应该注意的是,对正则表达式的支持有些奇怪。我在这里找到了PDF参考卡,该参考卡的左侧带有受支持的字符。
[编辑]
如“ @JohannesRössel”所述,您还可以将最后两行减少为一行。
((Get-ChildItem -Path $source) -match $filter) | Copy-Item -Destination $destination
主要区别在于Johannes的方法进行对象过滤,而我的方法进行文本过滤。使用Powershell时,使用对象几乎总是更好。
[EDIT2]
正如@smoknheap所提到的,以上脚本将整理文件夹结构并将所有文件放在一个文件夹中。我不确定是否有保留文件夹结构的开关。我尝试了-Recurse开关,但没有帮助。使它起作用的唯一方法是返回字符串操作并将文件夹添加到我的过滤器中。
$bin = Get-ChildItem -Path $source -Recurse | Where-Object {($_.Name -match $filter) -or ($_.PSIsContainer)}
foreach ($item in $bin) {
Copy-Item -Path $item.FullName -Destination $item.FullName.ToString().Replace($source,$destination).Replace($item.Name,"")
}
我敢肯定有一种更优雅的方法可以做到这一点,但是从我的测试来看,它是可行的。它收集所有内容,然后过滤名称匹配和文件夹对象。我必须使用ToString()方法来访问字符串操作。
[EDIT3]
现在,如果您要报告路径,以确保一切正确。您可以使用“写入主机”命令。这是将为您提供提示的代码。
cls
$source = "C:\test"
$destination = "C:\test2"
$filter = [regex] "^[0-9]{6}\.(jpg|gif)"
$bin = Get-ChildItem -Path $source -Recurse | Where-Object {($_.Name -match $filter) -or ($_.PSIsContainer)}
foreach ($item in $bin) {
Write-Host "
----
Obj: $item
Path: "$item.fullname"
Destination: "$item.FullName.ToString().Replace($source,$destination).Replace($item.Name,"")
Copy-Item -Path $item.FullName -Destination $item.FullName.ToString().Replace($source,$destination).Replace($item.Name,"")
}
这应该返回相关的字符串。如果您什么都没找到,就会知道哪个项目有问题。
希望这可以帮助
$item.FullName
那里使用-如果传递FileInfo对象,则会自动采用适当的属性(恕我直言,您不应该这样做,因为PowerShell的功能来自传递结构化对象,而不是字符串)。此外,您可以将所有内容放入一个单一的管道中:(((gci $source) -match $filter) | cp -dest $destination
为简洁起见,略有改动-随时可以更改;我只是说在foreach
那里没有必要)。
Copy-Item : Cannot bind argument to parameter 'Path' because it is null
Trim
并不是要从另一个字符串的末尾删除一个字符串,而是要从调用它的字符串的开头和结尾删除参数字符串中所有字符的实例。在您的情况下,如果$item.Name
包含大写字母C,它还将从字符串开头删除驱动器号C。
PowerShell是完成该任务的出色工具。您可以使用Copy-Item cmdlet进行复制过程。你可以与其他cmdlet复杂的复制命令管道吧,这里是有人确实做到了:)
正则表达式使用System.Text.RegularExpressions命名空间中的.NET RegEx类,这些类上有快速操作方法
PowerShell还具有-match和-replace运算符,可在通过copy-item进行管道传输时使用
还有一些工具可以帮助您创建RegEx本身,例如RegEx好友
-match
并且-replace
在进入之前应该被提及System.Text.RegularExpressions.RegEx
。至少对我来说,我很少[regex]
直接使用。然而,我也经常使用-match
和-replace
运营商。至于创建正则表达式,我发现PowerShell在测试和完善您正在编写的正则表达式方面也非常有用。