在 powershell 中过滤和删除早于 x 天的文件和文件夹(以及文件夹内的文件)

Filter and delete files and folders(and files inside of folders) older than x days in powershell

这是我第一次 post 在这个论坛上。我是编码初学者,我需要帮助使用我的第一个自编码工具之一。 我制作了一个小脚本,它根据文件是否早于日期 x (lastwritetime) 来删除文件。现在我的问题是:我希望脚本还检查目录内文件夹内的文件,并且仅在文件夹确实为空时才删除文件夹。我不知道如何解决这个问题中的递归,似乎脚本只删除了与日期 x 相关的整个文件夹。谁能告诉我我在此代码中遗漏了什么并帮助我创建自己的递归来解决问题或修复代码?谢谢大家,伙计们!这是我的代码:

如果有人知道如何使用函数使代码工作,我会很高兴


$path = Read-Host "please enter your path"
"
"

$timedel = Read-Host "Enter days in the past (e.g -12)"

$dateedit = (Get-Date).AddDays($timedel)
"
"
Get-ChildItem $path -File -Recurse | foreach{ if ($_.LastWriteTime -and !$_.LastAccessTimeUtc -le $dateedit) {

Write-Output "older as $timedel days: ($_)" } }

" 
"
pause

Get-ChildItem -Path $path -Force -Recurse | Where-Object { $_.PsisContainer -and $_.LastWriteTime -le $dateedit } | Remove-Item -Force -Recurse 

""
Write-Output "Files deleted"

如果文件夹是空的,要同时删除早于过去设定日期的文件夹,您会遇到这样的问题,即从此类文件夹中删除文件后,文件夹的 LastWriteTime 将设置为该文件夹及时。

这意味着您应该先获取旧文件夹的列表,在您开始删除旧文件之前,然后使用该列表删除这些文件夹(如果它们是空的)。

此外,应该对来自 Read-Host 的用户输入进行最少的检查。 (即路径必须存在并且天数必须可转换为整数。对于后者,我选择简单地将其转换为 [int] 因为如果失败,代码无论如何都会生成一个 execption。

试试

$path = Read-Host "please enter your path"
# test the user input
if (-not (Test-Path -Path $path -PathType Container)) {
    Write-Error "The path $path does not exist!" 
}
else {
    $timedel = Read-Host "Enter days in the past (e.g -12)"

    # convert to int and make sure it is a negative value
    $timedel  = -[Math]::Abs([int]$timedel)
    $dateedit = (Get-Date).AddDays($timedel).Date  # .Date sets this date to midnight (00:00:00)

    # get a list of all folders (FullNames only)that have a LastWriteTime older than the set date.
    # we check this list later to see if any of the folders are empty and if so, delete them.
    $folders = (Get-ChildItem -Path $path -Directory -Recurse | Where-Object { $_.LastWriteTime -le $dateedit }).FullName

    # get a list of files to remove
    Get-ChildItem -Path $path -File -Recurse | Where-Object { $_.LastWriteTime -le $dateedit} | ForEach-Object {
        Write-Host "older as $timedel days: $($_.FullName)" 
        $_ | Remove-Item -Force -WhatIf  # see below about the -WhatIf safety switch
    }

    # now that old files are gone, test the folder list we got earlier and remove any if empty
    $folders | ForEach-Object {
        if ((Get-ChildItem -Path $_ -Force).Count -eq 0) {
            Write-Host "Deleting empty folder: $_" 
            $_ | Remove-Item -Force -WhatIf  # see below about the -WhatIf safety switch
        }
    }

    Write-Host "All Done!" -ForegroundColor Green
}

Remove-Item 上使用的 -WhatIf 开关是为了您自己的安全。这样一来,实际上没有文件或文件夹被删除,而是在控制台中写入了 would 将被删除的内容。如果您认为这一切都很好,请再次删除 -WhatIf 和 运行 代码以真正删除文件和文件夹

param(
    [IO.DirectoryInfo]$targetTolder = "d:\tmp",
    [DateTime]$dateTimeX = "2020-11-15 00:00:00"
)

Get-ChildItem $targetTolder -Directory -Recurse | Sort-Object {$_.FullName} -Descending | ForEach-Object {
    Get-ChildItem $_ -File | Where-Object {$_.LastWriteTime -lt $dateTimeX} | Remove-Item -Force
    if ((Get-ChildItem $_).Count -eq 0){Remove-Item $_ -Force} 
}

测试后删除 -WhatIf

尝试这样的事情:

$timedel=-12

#remove old files
Get-ChildItem "C:\temp" -Recurse -File | Where LastWriteTime  -lt  (Get-Date).AddDays($timedel)  | Remove-Item -Force

#remove directory without file
Get-ChildItem "C:\temp\" -Recurse -Directory | where {(Get-ChildItem $_.FullName -Recurse -File).count -eq 0} | Remove-Item -Force -recurse