How to organize your Downloads folder by file type
Turn a Downloads folder with hundreds of loose files into Images/, Documents/, Videos/, Spreadsheets/, Archives/ and Installers/ in one go.
Images/screenshot.png, for example). Both scripts below follow them.Windows: PowerShell (built in)
Open PowerShell, go to the folder with cd $HOME\Downloads, and paste this. As written it only shows the plan:
$preview = $true # change to $false to actually move the files
$types = @{
Images = '.jpg', '.jpeg', '.png', '.gif', '.webp', '.heic'
Videos = '.mp4', '.mov', '.mkv', '.avi'
Documents = '.pdf', '.doc', '.docx', '.odt', '.txt'
Spreadsheets = '.xls', '.xlsx', '.ods', '.csv'
Archives = '.zip', '.rar', '.7z'
Installers = '.exe', '.msi'
}
Get-ChildItem -File | ForEach-Object {
$file = $_
$dir = $types.Keys | Where-Object { $types[$_] -contains $file.Extension } | Select-Object -First 1
if (-not $dir) { return }
if ($preview) { "$($file.Name) -> $dir\" }
else {
New-Item -ItemType Directory -Force -Path $dir | Out-Null
Move-Item -LiteralPath $file.FullName -Destination $dir
}
}
The plan looks like this (extensions match in any case, so .JPG counts as an image):
bank export.csv -> Spreadsheets\
clip.MP4 -> Videos\
Holiday photo.JPG -> Images\
invoice.pdf -> Documents\
photos.zip -> Archives\
screenshot.png -> Images\
setup.exe -> Installers\
Happy with it? Paste it again with $preview = $false. If a file with the same name is already in the target folder, Move-Item shows a red error for that file and leaves both files alone. Tested in PowerShell 7.4.
macOS and Linux: a small bash script
Save this as organize.sh in your home folder:
#!/usr/bin/env bash
# Sort the files in the current folder into sub-folders by type.
# "bash organize.sh" only shows the plan; "bash organize.sh apply" moves the files.
shopt -s nocasematch
for f in *; do
[ -f "$f" ] || continue
case "$f" in
*.jpg|*.jpeg|*.png|*.gif|*.webp|*.heic) dir=Images ;;
*.mp4|*.mov|*.mkv|*.avi) dir=Videos ;;
*.pdf|*.doc|*.docx|*.odt|*.txt) dir=Documents ;;
*.xls|*.xlsx|*.ods|*.csv) dir=Spreadsheets ;;
*.zip|*.rar|*.7z|*.tar|*.gz) dir=Archives ;;
*.exe|*.msi|*.dmg|*.pkg|*.deb) dir=Installers ;;
*) continue ;;
esac
if [ "$1" = apply ]; then
mkdir -p "$dir" && mv -n -- "$f" "$dir/"
else
echo "$f -> $dir/"
fi
done
Then run it from the folder you want to sort (on macOS run it with bash as shown, even though the default shell is zsh):
cd ~/Downloads
bash ~/organize.sh # preview
bash ~/organize.sh apply # move the files
mv -n never overwrites: a file whose name is already taken in the target folder simply stays where it is, so anything left behind after the run is a name clash to check by hand.
Want an undo? TidyBatch Pro
tidybatch organize does the same sort with a preview by default, gives clashing names a _1 suffix instead of skipping them, puts unknown types in Other/, and records everything so one command puts it all back. Real output on the same test folder (which already had an Images/screenshot.png):
$ tidybatch organize ./Downloads
bank export.csv -> Spreadsheets/bank export.csv
clip.MP4 -> Videos/clip.MP4
Holiday photo.JPG -> Images/Holiday photo.JPG
invoice.pdf -> Documents/invoice.pdf
notes -> Other/notes
photos.zip -> Archives/photos.zip
screenshot.png -> Images/screenshot_1.png
setup.exe -> Installers/setup.exe
8 file(s) would change.
Dry run: nothing was changed. Add --apply to do it.
Add --apply to do it, and tidybatch undo ./Downloads to restore every file to where it was (the folders it created are removed again). Other ways to sort:
tidybatch organize ./Downloads --by ext # PDF/, JPG/, ZIP/ …
tidybatch organize ./Archive --by date -r # 2024/08/ by modified date
tidybatch organize ./Camera --by taken -r # 2023/07/ by photo date taken
organize is part of TidyBatch Pro (one-time purchase, ready-to-run apps for Windows and Linux). The two scripts above are free.
Which one should you use?
| PowerShell / bash script | TidyBatch Pro | |
|---|---|---|
| Preview before moving | ✓ | ✓ default |
| Never overwrites | ✓ clashes are skipped | ✓ clashes get _1 |
| Undo afterwards | — (move back by hand) | ✓ tidybatch undo |
| By date, by photo date taken, by extension | edit the script | ✓ --by |
| Price | free | paid, one-time |