PowerShell查找密码保护PDF并移动文件夹时文件锁定问题求助
问题原因
OpenText()方法返回的StreamReader对象没有被显式释放,持有的文件句柄会一直保留到PowerShell垃圾回收自动清理,时机晚于移动操作执行,导致文件占用报错。
可行解决方案
方案1:使用[System.IO.File]::ReadAllText()(推荐)
该静态方法读完文件后会自动释放所有资源,不需要手动处理句柄,修改后完整代码如下:
$Source = 'sourcefolder' $Dest = 'Destinationfolder' Get-ChildItem -Path $Source -Directory | ForEach-Object { $hasEncryptedPdf = Get-ChildItem -Path $_.FullName -Filter *.pdf -File | Where-Object { [System.IO.File]::ReadAllText($_.FullName).Contains("Encrypt") } | Measure-Object | Select-Object -ExpandProperty Count if ($hasEncryptedPdf -gt 0) { Move-Item -Path $_.FullName -Destination $Dest -Force -Verbose } }
方案2:使用using块管理StreamReader
如果要保留原有的StreamReader用法,用using块自动释放对象,退出块后文件锁会立即解除:
$Source = 'sourcefolder' $Dest = 'Destinationfolder' Get-ChildItem -Path $Source -Directory | ForEach-Object { If (Get-ChildItem -Path $_.FullName -Filter *.pdf | Where-Object { $isEncrypted = $false using ($reader = $_.OpenText()) { $isEncrypted = $reader.ReadToEnd().Contains("Encrypt") } return $isEncrypted }) { Move-Item -Path $_.FullName -Destination $Dest -Force -Verbose } }
优化建议
如果需要处理大体积PDF,可以只读取文件头部1024字节判断(PDF加密标记通常在文件头范围内),大幅降低IO开销:
# 替换Where-Object内的判断逻辑即可 Where-Object { $header = [byte[]]::CreateInstance([byte], 1024) using ($fs = [System.IO.File]::OpenRead($_.FullName)) { $fs.Read($header, 0, $header.Length) | Out-Null } return [System.Text.Encoding]::ASCII.GetString($header).Contains("Encrypt") }
内容的提问来源于stack exchange,提问作者Michael Moore
相关产品推荐
相关产品推荐

