我有一个无效的脚本:
$files = Get-ChildItem "C:\test\"
for ($i=0; $i -lt $files.Count; $i++) {
$outfile = $files[$i].FullName + "out"
Get-Content $files[$i].FullName | ? {$_.Trim() -ne "" } | Set-Content $files[$i].FullName
}
错误是:
Set-Content : The process cannot access the file 'C:\test\ADMINISTRATOR.txt' because it is being use At D:\skriptablank.ps1:4 char:63 + Get-Content $files[$i].FullName | ? {$_.Trim() -ne "" } | Set-Content $files ... + ~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Set-Content], IOException + FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.SetContentCommand
你怎么想,我做错了什么?
答案 0 :(得分:2)
您在管道中的同一文件上使用Get-Content
和Set-Content
:
Get-Content $files[$i].FullName | ... | Set-Content $files[$i].FullName
当您执行此操作时,通常仍会在Set-Content
开始写入文件时读取该文件,从而导致您观察到的错误。在开始写作之前,你需要完成阅读:
(Get-Content $files[$i].FullName) | ... | Set-Content $files[$i].FullName
或首先写入临时文件,然后用临时文件替换原始文件:
Get-Content $files[$i].FullName | ... | Set-Content "$env:TEMP\foo.txt"
Move-Item "$env:TEMP\foo.txt" $files[$i].FullName -Force
对于小文件,您通常希望使用第一种方法,因为将整个文件读入内存而不是逐行读取它会更快,更容易处理。
对于大文件,您通常希望使用第二种方法以避免内存耗尽。确保在与要替换的文件相同的文件系统上创建临时文件,这样在移动临时文件时就不必再次复制整个数据了(在文件系统/卷中移动操作只需要更改对文件的引用,这比转移文件的内容要快得多。