3
\$\begingroup\$

I am sick of File Explorer's super slow deletion speed, so I tried to write a PowerShell script to make deletion faster, and while it does its job, its speed isn't as high as what I intended it to be.

I have written this:

Function Fast-Delete {
    Param(
    [Parameter(Valuefrompipeline=$True, Mandatory=$True)] [String]$Directory0
    )
    Write-Warning "This Process Will Delete Everything In The Target Directory: $Directory0, Do You Want To Confirm Deletion?" -Warningaction Inquire
    $Directory=$Directory0
    While ((Get-Childitem -Path $Directory0 -Depth 0 -Force).Count -Ne 0) {
    If ((Get-Childitem -Path $Directory -Directory -Force -Depth 0).Count -Ne 0) {
    $Directory=(Get-Childitem -Path $Directory -Directory -Force -Depth 0).Fullname | Select-Object -Index 0
    }
    If ((Get-Childitem -Path $Directory -File -Force).Count -Ne 0) {
    (Get-Childitem -Path $Directory -File -Recurse -Force).Fullname | Foreach {Remove-Item -Path $_}
    }
    $Directory1=$Directory
    $Directory=$Directory | Split-Path -Parent
    Remove-Item -Path $Directory1
    }
    Remove-Item -Path $Directory0
}

It is significantly faster than explorer, but still isn't ideal, I have tested it, I used it to delete 208,000 files in 1,000 folders , and the folders disappear at speed of 1 per second, so it's about 208 files/s, now the next challenge should be parallelization, But this is currently really way above me, but it shouldn't be too hard, I am just not experienced enough.

Update2

I have managed to make it run in parallel with this script:

function Parallel-Delete {
    param(
    [Parameter(Valuefrompipeline=$true, Mandatory=$true, Position=0)] [array]$filelist,
    [Parameter(Valuefrompipeline=$true, Mandatory=$true, Position=1)] [int]$number
    )
    0..($filelist.count-1) | Where-Object {$_ % 16 -eq $number} | foreach {Remove-Item -Path $filelist[$_]}
}

Function Fast-Delete {
    Param(
    [Parameter(Valuefrompipeline=$True, Mandatory=$True)] [String]$Directory0
    )
    Write-Warning "This Process Will Delete Everything In The Target Directory:  $Directory0, Do You Want To Confirm Deletion?" -Warningaction Inquire
    $Directory=$Directory0
    While ((Get-Childitem -Path $Directory0 -Depth 0 -Force).Count -Ne 0) {
        If ((Get-Childitem -Path $Directory -Directory -Force -Depth 0).Count -Ne 0) {
            $Directory=(Get-Childitem -Path $Directory -Directory -Force -Depth 0).Fullname | Select-Object -Index 0
        }
        If ((Get-Childitem -Path $Directory -File -Force).Count -Ne 0) {
            If ((Get-Childitem -Path $Directory -File -Force).Count -Ge 128) {
                [array]$filelist=(Get-Childitem -Path $Directory -File -Force).Fullname
                0..15 | foreach-object {Invoke-Command -ScriptBlock { Parallel-Delete $filelist $_}}
                } else {
                (Get-Childitem -Path $Directory -File -Force).Fullname | Foreach {Remove-Item -Path $_}
            }
        }
        $Directory1=$Directory
        $Directory=$Directory | Split-Path -Parent
        Remove-Item -Path $Directory1
        }
    Remove-Item -Path $Directory0 -erroraction silentlycontinue
}
$Directory0=Read-Host "Please input target directory to be deleted"
Fast-Delete $Directory0

But it still isn't ideal, it isn't 15 times faster as expected, what did I miss?

Edit: simplified the creation of parallel processes.

\$\endgroup\$
7
  • 2
    \$\begingroup\$ the fastest way to delete an entire dir tree is to use robocopy. you mirror a blank "source" dir to the one you want removed ... and the "destination" gets emptied quickly. [grin] \$\endgroup\$ – Lee_Dailey Dec 9 '20 at 7:33
  • \$\begingroup\$ @Lee_Dailey, in fact I wanted to write a new script, not to use existing things, and the method you mentioned sounds like a bug... \$\endgroup\$ – Xeнεi Ξэnвϵς Dec 9 '20 at 7:51
  • 3
    \$\begingroup\$ i understand your desire. [grin] as for a bug ... it is exactly what the options mean - mirror empty source to full destination gives empty source and empty destination. so ... have fun playing with a script ...but PoSh will always be slower than any well written utility. \$\endgroup\$ – Lee_Dailey Dec 9 '20 at 8:08
  • \$\begingroup\$ And I have tried Start-Job, but they just hang in place, they are not working so I used stop-job to terminate them... And still I can't pass to variables to new powershell process started by start-process... \$\endgroup\$ – Xeнεi Ξэnвϵς Dec 15 '20 at 10:37
  • \$\begingroup\$ i would narrow your problems to specifics ... and open a Question for each of them. the pass variable to start-process question has been answered here OR in stackoverflow many times. \$\endgroup\$ – Lee_Dailey Dec 15 '20 at 23:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.