因此,我编写了一个 PowerShell 脚本,经过一番苦恼之后,终于开始使用它。它可以删除我不再需要的文件,而且一切都很顺利。只有一个问题,无论文件是否被其他程序打开,它都会删除该文件,这很糟糕。我的代码如下:
# Change the value $oldTime in order to set a limit for files to be deleted.
$oldTime = [int]30 # 30 days
foreach ($path in Get-Content "pathList.txt") {
# Write information of what it is about to do
Write-Host "Trying to delete files older than $oldTime days, in the folder $path" -ForegroundColor Green
# deleting the old files
Get-ChildItem $path -Recurse -filter "*EDI*" | WHERE {$_.LastWriteTime -le $(Get-Date).AddDays(-$oldTime)} | Remove-Item -Force
我只需要一种方法让脚本看到文件已打开,跳过该文件并继续。我在 Windows 7 SP1 上运行 PowerShell 2.0。
答案1
通常,尝试测试文件是否锁定可能会导致各种竞争条件,因为文件可能在我们检查后立即被另一个线程/进程锁定。并且检查本身需要锁定,除非它不是通过仅从 Windows Vista 开始提供的 Restart Manager API 完成的(请参阅这个答案)所以你已经被警告了。
这是 PowerShell 函数,它将检查文件是否被锁定。根据以下问题改编为 PowerShell:https://stackoverflow.com/questions/876473/is-there-a-way-to-check-if-a-file-is-in-use
复制粘贴或与脚本一起保存Test-IsFileLocked.ps1
并使用点源加载:
$ScriptDir = Split-Path $script:MyInvocation.MyCommand.Path
. (Join-Path -Path $ScriptDir -ChildPath 'Test-IsFileLocked.ps1')
然后将脚本的最后一行更改为:
Get-ChildItem $path -Recurse -filter "*EDI*" | WHERE {($_.LastWriteTime -le $(Get-Date).AddDays(-$oldTime)) -and !(Test-IsFileLocked -Files $_.FullName)} | Remove-Item -Force
Test-IsFileLocked
函数本身:
function Test-IsFileLocked
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]$Files
)
Process
{
# Foreach loop to accept arrays either from pipeline or Files parameter
foreach ($file in $Files)
{
$Locked = $false
try
{
# Try to open file
$Test = [System.IO.File]::Open($file, 'Open', 'ReadWrite', 'None')
# Close file and dispose object if succeeded
$Test.Close()
$Test.Dispose()
}
catch
{
# File is locked!
$Locked = $true
}
# Write file status to pipeline
$Locked
}
}
}