Tidy your Downloads folder
Every Sunday evening, files older than a week are moved out of the Downloads pile into folders by type: Documents, Images, Videos, Audio, Archives, Installers and Other. Nothing is deleted, and a file with the same name is never overwritten.
1. Save the script
Make a folder called Scripts in your user folder (for example C:\Users\Thandi\Scripts), then save this file into it as tidy-downloads.ps1. Use Download below, or Copy and paste it into Notepad.
<#
Tidy the Downloads folder: files older than a number of days are moved into
subfolders by type (Documents, Images, Videos, Audio, Archives, Installers, Other).
It only shows what it would do unless you add -Apply, and it never overwrites or
deletes anything.
powershell -ExecutionPolicy Bypass -File .\tidy-downloads.ps1 preview only
powershell -ExecutionPolicy Bypass -File .\tidy-downloads.ps1 -Apply move the files
Free from Voypelo Solutions, voypelo.co.za. MIT licence.
#>
param(
[string]$Folder = (Join-Path $env:USERPROFILE 'Downloads'),
[int]$OlderThanDays = 7,
[switch]$Apply
)
$types = [ordered]@{
'Documents' = @('.pdf', '.doc', '.docx', '.xls', '.xlsx', '.csv', '.ppt', '.pptx', '.txt', '.rtf', '.odt')
'Images' = @('.jpg', '.jpeg', '.png', '.gif', '.heic', '.webp', '.bmp', '.svg')
'Videos' = @('.mp4', '.mov', '.avi', '.mkv', '.wmv')
'Audio' = @('.mp3', '.wav', '.m4a', '.ogg', '.opus')
'Archives' = @('.zip', '.rar', '.7z', '.tar', '.gz')
'Installers' = @('.exe', '.msi')
}
# Files still downloading or used by Windows itself are left alone.
$skip = @('.crdownload', '.part', '.tmp', '.ini', '.lnk')
if (-not (Test-Path -LiteralPath $Folder -PathType Container)) {
Write-Error "Expected a folder at $Folder, found nothing there"
exit 1
}
$cutoff = (Get-Date).AddDays(-$OlderThanDays)
$count = 0
Get-ChildItem -LiteralPath $Folder -File |
Where-Object { $_.LastWriteTime -lt $cutoff -and $skip -notcontains $_.Extension.ToLower() } |
ForEach-Object {
$ext = $_.Extension.ToLower()
$target = 'Other'
foreach ($name in $types.Keys) {
if ($types[$name] -contains $ext) { $target = $name; break }
}
$destDir = Join-Path $Folder $target
$dest = Join-Path $destDir $_.Name
# Never overwrite: a file with the same name gets a number added.
$n = 1
while (Test-Path -LiteralPath $dest) {
$dest = Join-Path $destDir ('{0} ({1}){2}' -f $_.BaseName, $n, $_.Extension)
$n++
}
if ($Apply) {
New-Item -ItemType Directory -Path $destDir -Force | Out-Null
Move-Item -LiteralPath $_.FullName -Destination $dest
Write-Output ('moved {0} -> {1}' -f $_.Name, $target)
} else {
Write-Output ('would move {0} -> {1}' -f $_.Name, $target)
}
$count++
}
if ($Apply) {
Write-Output ('{0} file(s) moved.' -f $count)
} else {
Write-Output ('{0} file(s) would be moved. Run again with -Apply to move them.' -f $count)
}2. Try it once
Open Command Prompt and run this. It only shows what it would move:
powershell -ExecutionPolicy Bypass -File "%USERPROFILE%\Scripts\tidy-downloads.ps1"If the list looks right, run it for real:
powershell -ExecutionPolicy Bypass -File "%USERPROFILE%\Scripts\tidy-downloads.ps1" -Apply3. Let Windows run it every week
Still in Command Prompt, paste this to run it every Sunday at 18:00:
schtasks /Create /SC WEEKLY /D SUN /ST 18:00 /TN "Tidy Downloads" /TR "powershell -NoProfile -ExecutionPolicy Bypass -File \"%USERPROFILE%\Scripts\tidy-downloads.ps1\" -Apply"To stop it later: schtasks /Delete /TN "Tidy Downloads".
Why it helps
A tidy Downloads folder means you find last month's invoice in seconds instead of scrolling past 400 files.