2026年01月21日/ 浏览 8
很多人下载文件后习惯放在“下载”文件夹,久而久之混乱难找。本文教你用一个可复用的 PowerShell 脚本,每天自动把 Downloads 中的文件按 文件类型(如 图片/文档/压缩/视频/音频/可执行)和创建日期归档到对应的子文件夹,并做去重与日志记录。零第三方,10 分钟上手。
为什么这样做(30 秒)
自动分类,节省找文件时间;支持按天或按月归档(按需切换);支持“演练模式”(dry-run)先预览改动,防止误操作;可用任务计划自动化、长期运行。准备(1 分钟)
Windows 11(或 Windows 10)带 PowerShell 即可。用户目录的 Downloads(或任意你希望整理的目录)。管理员权限非必须(除非你要整理系统目录)。把脚本放好(可直接复制粘贴)
在 C:\Scripts\ 下新建文件 AutoSortDownloads.ps1,把下面内容完整粘贴并保存:
<#
AutoSortDownloads.ps1
功能:按类型 + 日期(按日或按月)把下载目录中的文件移动到分类子目录
使用:PowerShell -ExecutionPolicy Bypass -File "C:\Scripts\AutoSortDownloads.ps1" [-Source "C:\Users\you\Downloads"] [-Mode "dryrun"|"apply"] [-DateMode "Daily"|"Monthly"]
说明:默认 source 为当前用户 Downloads,默认 Mode 为 dryrun(仅预览),默认 DateMode 为 Monthly
#>
param(
[string]$Source = "$env:USERPROFILE\Downloads",
[ValidateSet("dryrun","apply")]
[string]$Mode = "dryrun",
[ValidateSet("Daily","Monthly")]
[string]$DateMode = "Monthly",
[string[]]$Exclude = @("*.crdownload","*.tmp") # 排除规则(支持通配符)
)
# 配置区:按需修改
$Mapping = @{
"Images" = @("*.jpg","*.jpeg","*.png","*.gif","*.bmp","*.webp","*.heic")
"Documents" = @("*.pdf","*.doc","*.docx","*.xls","*.xlsx","*.ppt","*.pptx","*.txt","*.md")
"Archives" = @("*.zip","*.rar","*.7z","*.tar","*.gz","*.iso")
"Videos" = @("*.mp4","*.mkv","*.mov","*.avi","*.flv")
"Audio" = @("*.mp3","*.wav","*.flac","*.m4a")
"Executables"= @("*.exe","*.msi","*.bat","*.ps1")
"Others" = @("*") # 默认 catch-all
}
$LogDir = Join-Path $Source "AutoSortLogs"
if (-not (Test-Path $LogDir)) { New-Item -Path $LogDir -ItemType Directory | Out-Null }
$LogFile = Join-Path $LogDir ("AutoSort_{0}.log" -f (Get-Date -Format "yyyyMMdd"))
function Write-Log {
param($text)
$time = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
"$time`t$text" | Out-File -FilePath $LogFile -Encoding UTF8 -Append
}
function Should-Exclude {
param($name)
foreach ($pattern in $Exclude) {
if ($name -like $pattern) { return $true }
}
return $false
}
# 生成目标子目录名(按分类 + 日期)
function Get-TargetFolder {
param($baseFolder, $category, [datetime]$dt)
if ($DateMode -eq "Daily") {
$datePart = $dt.ToString("yyyy-MM-dd")
} else {
$datePart = $dt.ToString("yyyy-MM")
}
return Join-Path $baseFolder (Join-Path $category $datePart)
}
# 主流程
Write-Log "=== AutoSort start. Mode=$Mode; Source=$Source; DateMode=$DateMode ==="
if (-not (Test-Path $Source)) {
Write-Log "Source path not found: $Source. Exit."
throw "Source path not found: $Source"
}
# 枚举文件(不递归到子目录,仅整理 Source 根目录中的文件;如需递归改 -Recurse)
$files = Get-ChildItem -Path $Source -File -Force
foreach ($f in $files) {
$name = $f.Name
if (Should-Exclude $name) {
Write-Log "Skip excluded: $name"
continue
}
# 找到分类
$matchedCategory = $null
foreach ($cat in $Mapping.Keys) {
foreach ($pat in $Mapping[$cat]) {
if ($name -like $pat) {
$matchedCategory = $cat
break
}
}
if ($matchedCategory) { break }
}
if (-not $matchedCategory) { $matchedCategory = "Others" }
$targetFolder = Get-TargetFolder -baseFolder $Source -category $matchedCategory -dt $f.CreationTime
if (-not (Test-Path $targetFolder)) {
if ($Mode -eq "apply") { New-Item -Path $targetFolder -ItemType Directory -Force | Out-Null }
Write-Log "Create folder: $targetFolder"
}
# 目标文件路径
$targetPath = Join-Path $targetFolder $name
# 若目标已存在,重命名原文件(添加时间戳)
if (Test-Path $targetPath) {
$ts = (Get-Date).ToString("yyyyMMdd_HHmmss")
$base = [System.IO.Path]::GetFileNameWithoutExtension($name)
$ext = [System.IO.Path]::GetExtension($name)
$newName = "$base`_$ts$ext"
$targetPath = Join-Path $targetFolder $newName
Write-Log "Target exists. Renaming to: $newName"
}
if ($Mode -eq "dryrun") {
Write-Log "DRYRUN: Move $($f.FullName) -> $targetPath"
} else {
try {
Move-Item -Path $f.FullName -Destination $targetPath -Force
Write-Log "Moved: $($f.FullName) -> $targetPath"
} catch {
Write-Log "ERROR moving $($f.FullName): $_"
}
}
}
Write-Log "=== AutoSort finished ===`n"
如何使用(3 种常见场景)
1) 先预览(强烈推荐)
在 PowerShell(普通用户)中运行(脚本默认为 dryrun):
PowerShell -ExecutionPolicy Bypass -File "C:\Scripts\AutoSortDownloads.ps1" -Source "$env:USERPROFILE\Downloads" -Mode dryrun -DateMode Monthly
查看 Downloads\AutoSortLogs\AutoSort_yyyyMMdd.log,确认脚本会做的改动。
2) 真正执行一次(手动触发)
确认无误后执行:
PowerShell -ExecutionPolicy Bypass -File "C:\Scripts\AutoSortDownloads.ps1" -Mode apply -DateMode Monthly
3) 定时自动化(每天晚间自动整理)
用任务计划程序每天某个时间运行(例如 23:30):
通过 schtasks 创建每天 23:30 运行任务(当前用户):
schtasks /Create /SC DAILY /TN "AutoSortDownloads" /TR "PowerShell -ExecutionPolicy Bypass -File \"C:\Scripts\AutoSortDownloads.ps1\" -Mode apply -DateMode Monthly" /ST 23:30
或在任务计划程序 GUI 中创建:创建任务 → 常规填写名称 → 触发器设置为每天23:30 → 操作选择启动程序 powershell.exe,参数填写 -ExecutionPolicy Bypass -File "C:\Scripts\AutoSortDownloads.ps1" -Mode apply -DateMode Monthly。
常见选项说明(可按需修改)
-DateMode:Daily 按日期(例如 Images\2025-11-10),Monthly 按月(例如 Images\2025-11)。-Exclude:脚本顶部可修改默认排除规则(例如临时下载 .crdownload、.tmp)。Mapping:在脚本中修改 $Mapping 字典来调整分类与扩展名。是否递归整理子目录:当前脚本仅整理根目录文件(避免移动已整理的子目录内文件),如需递归把 Get-ChildItem 加上 -Recurse 并排除目标子目录。去重策略:当前策略是目标存在则为移动的文件添加时间戳后再移动,避免覆盖。测试建议(安全第一)
先在一个临时目录测试(复制几个示例文件到 C:\Temp\DownloadsTest),用 -Source 指向该目录并先运行 -Mode dryrun 查看日志。观察日志确认无问题后切换 -Mode apply。若你担心误删或移动重要文件,可先备份 Downloads 文件夹(复制到外部硬盘或压缩打包)。常见问题解答
Q:会不会把重要未分类文件误删?A:脚本只 移动 文件,不会删除,且默认是 dryrun 模式。请务必先 dryrun。Q:能否把图片按拍照日期归档?A:可把 Get-ChildItem 中读取的 CreationTime 改为读取 EXIF 的拍摄时间(需要额外读取图片元数据)。如需我可以提供扩展示例。Q:如何处理大量小文件导致性能问题?A:可把脚本拆成批次(例如一次处理前 N 个文件),或在低峰期运行(夜间)。小结(你将获得)
一个可复制、可定制的 PowerShell 脚本(含 dryrun)用于自动整理下载目录;一条 schtasks 命令用于每天自动执行;日志记录和防止覆盖的去重策略,保证安全可回溯。