我有以下 PowerShell 脚本,我用它来移动包含特定字符串的目录中的所有文件:
gci -Path 'C:\Users\LG\Desktop\3039u\*.txt' -r|sls -Pattern '(?-i)^Engine:'|Move-Item -Destination "C:\Users\LG\Desktop"
但是,当尝试执行它时,我收到错误消息:
Move-Item : The process cannot access the file because it is being used by another process.
At line:1 char:77
+ ... -Pattern '(?-i)^Engine:'|Move-Item -Destination "C:\Users\LG\Desktop"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (C:\Users\LG\Des...Zeus ZEU-6T.txt:FileInfo) [Move-Item], IOException
+ FullyQualifiedErrorId : MoveFileInfoItemIOError,Microsoft.PowerShell.Commands.MoveItemCommand
对 sls 选择且 Move-Item 尝试移动的每个文件重复此操作。我已经使用 Process Explorer (Sysinternals) 验证没有其他进程使文件保持打开状态。这可能是命令编写不正确的问题,即 sls 在收集所有匹配文件的列表时保持文件打开,导致 Move-Item 无法访问它们?如果是这样,我应该如何重新格式化命令?
要明确的是 - 我希望它使用 sls 找到每个匹配的文件,然后将每个匹配移动到不同的文件夹。
问候
Select-String
(sls
别名的目标)可能会在完成读取给定文件之前输出匹配项 - 解释为什么您无法移动该文件,因为Select-String
仍然有一个打开的句柄。
您可以将操作分为 2 个管道,允许
Select-String
在开始移动文件之前完成搜索:
$FilesToMove = Get-ChildItem -Path 'C:\Users\LG\Desktop\3039u\*.txt' -Recurse |Select-String -Pattern '(?-i)^Engine:'
$FilesToMove |Move-Item -Destination "C:\Users\LG\Desktop"
然而,更有效的方法是一次仅针对 1 个文件调用
Select-String
- 这也允许您在获得第一个匹配项后立即停止 Select-String
:
Get-ChildItem -Path 'C:\Users\LG\Desktop\3039u\*.txt' -Recurse |ForEach-Object {
$_ |Select-String -Pattern '(?-i)^Engine:' |Select-Object -First 1 |Move-Item -Destination "C:\Users\LG\Desktop"
}