约 1939 字

约 10 分钟

#文件整理

#题目

编写一个 PowerShell 脚本,把指定目录中的文件按扩展名移动到对应的子目录。例如:

downloads/
├── report.pdf
├── photo.jpg
├── notes.txt
└── archive.zip

整理后:

downloads/
├── pdf/
│   └── report.pdf
├── jpg/
│   └── photo.jpg
├── txt/
│   └── notes.txt
└── zip/
    └── archive.zip

#要求

  • 接收一个目录路径作为参数,路径不存在时给出错误并退出。
  • 只处理当前目录下的文件,不递归处理子目录。
  • 子目录名使用小写扩展名,例如 .PDF 和 .pdf 归入同一个 pdf 目录。
  • 没有扩展名的文件放入 noext 目录。
  • 重复运行脚本不应报错。

#参考实现

organize.ps1

param(
    [Parameter(Mandatory)]
    [string]$Path
)

if (-not (Test-Path -LiteralPath $Path -PathType Container)) {
    Write-Error "目录不存在:$Path"
    exit 1
}

$files = Get-ChildItem -LiteralPath $Path -File

foreach ($file in $files) {
    $ext = $file.Extension.TrimStart('.').ToLowerInvariant()
    if ([string]::IsNullOrEmpty($ext)) {
        $ext = 'noext'
    }

    $destination = Join-Path $Path $ext
    if (-not (Test-Path -LiteralPath $destination)) {
        New-Item -ItemType Directory -Path $destination | Out-Null
    }

    Move-Item -LiteralPath $file.FullName -Destination $destination
}

运行:

> ./organize.ps1 -Path ~/Downloads

#讲解

  • Get-ChildItem -File 只返回文件,自动跳过子目录;配合 -LiteralPath 可以避免路径中的通配符被解释。
  • $file.Extension 返回带点的扩展名,例如 .pdf;TrimStart('.') 去掉点,ToLowerInvariant() 统一为小写。
  • [string]::IsNullOrEmpty($ext) 判断没有扩展名的情况,目录名用 noext。
  • Join-Path 负责拼接路径,避免手动处理 Windows 与 Linux 的分隔符差异。
  • Test-Path 先判断目标目录是否存在,不存在才用 New-Item 创建,保证幂等。
  • Move-Item 移动文件。如果目标位置已有同名文件,命令会报错;需要覆盖时可以加 -Force,但应先确认不会误删数据。

调试时可以先加 -WhatIf 查看将要执行的操作:

> Move-Item -LiteralPath $file.FullName -Destination $destination -WhatIf

#推荐阅读

更新: 2026/11/2

作者: planc

创建: 2026/11/2