You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PowerShell单参数中接收多文件或单目录输入

问题与解决方案:PowerShell脚本接收多文件/目录输入的参数处理

背景

我正在编写基于FFmpeg处理文件的PowerShell脚本,目标适配Windows自带的PowerShell v5.1,若无法实现则使用最新版PowerShell。为了能从「运行」或命令提示符直接执行脚本,我用批处理调用:

@echo off
powershell -File .\ff.ps1 %*

这样就能从命令提示符向PowerShell脚本传递所有参数。

命令语法(命令提示符中):

> ff mp3 [可选参数] <多文件>|<单目录>

传入空格分隔的多文件时,脚本处理这些文件;传入单个目录时,处理该目录内所有文件(不含子目录)。

现有参数定义

我已经在脚本顶部定义了包含子命令的参数:

[CmdletBinding()]
param(
  [Parameter()][Boolean]$loop = $true,
  [Parameter()][Boolean]$twoPass = $true,
  [Parameter()][Int]$height = -1,
  [Parameter()][Int]$width = 1280,
  [Parameter()][Int]$quality = 80,
  [Parameter()][Int]$samplerate = 48000,
  [Parameter()][Int]$compression = 6,
  [Parameter()][Int]$giType = 1,
  [Parameter()][Int]$fps = 24,
  [Parameter()][Int]$bitrate = 320,
  [Parameter()][String]$preset = "picture",
  [Parameter()][Switch]$lossless = $false,
  [Parameter(Position = 0, Mandatory = $true)][String]$subcmd = ""
)

目前子命令能正常设置,但不知道如何添加参数接收<多文件>|<单目录>的输入。

支持的输入格式

该参数需要支持以下输入格式:

// 当前目录下单个文件
01.mp4
.\01.mp4
// 当前目录下多个文件
01.jpg 02.jpg 03.jpg 04.jpg
.\01.jpg .\02.jpg 03.jpg 04.jpg
// 子目录下单个文件
subdir\01.png
.\subdir\01.png
// 子目录下多个文件
subdir\01.png subdir\02.jpg subdir\03.webp
.\subdir\01.png .\subdir\02.jpg .\subdir\03.webp
// 通配符
*.png
.\*.png
subdir2\*.mp3
.\subdir2\*.mp3
// 多通配符(含子目录)
*.png *.jpg
.\*.png .\*.jpg
subdir2\image_*.png subdir2\image_*.jpg
.\subdir2\image_*.png .\subdir2\image_*.jpg
*.png subdir2\*.png
*.png .\subdir2\*.png

// 当前目录下单个子目录
subdir3
.\subdir3
// 子目录中的单个目录
.\subdir3\subdir4
subdir3\subdir4
// 绝对路径
C:\another_dir

所有通配符和相对路径需要解析为绝对路径,最终得到供FFmpeg处理的完整文件列表(后续会过滤不兼容格式,此为另一问题)。

脚本使用示例(PowerShell中)

PS> ff.ps1 mp3 -bitrate 320 01.mp4 subdir\*.avi 00.webp // '00.webp'将在处理前被过滤
PS> ff.ps1 webpa -loop 0 subdir // 获取'subdir'内所有文件并过滤后处理

核心问题

如何通过单个参数接收上述格式的<多文件>|<单目录>输入,并转换为文件列表?


解决方案

1. 添加可变位置参数

在param块中添加一个可变长度的位置参数,用于收集所有剩余的输入(文件/目录/通配符):

[Parameter(Position = 1, Mandatory = $true, ValueFromRemainingArguments = $true)]
[String[]]$InputPaths
  • Position = 1:指定该参数在子命令(Position=0)之后
  • ValueFromRemainingArguments = $true:将所有未被其他参数匹配的输入都收集到这个数组中
  • Mandatory = $true:确保必须传入至少一个路径

2. 解析路径并生成文件列表

添加代码块处理$InputPaths,将其转换为绝对路径的文件列表:

$fileList = @()
foreach ($path in $InputPaths) {
    # 解析相对路径、通配符为绝对路径
    $resolvedPaths = Resolve-Path -Path $path -ErrorAction SilentlyContinue
    if (-not $resolvedPaths) {
        Write-Warning "路径无效或不存在: $path"
        continue
    }
    foreach ($resolved in $resolvedPaths) {
        if (Test-Path -Path $resolved.Path -PathType Container) {
            # 若为目录,获取目录内所有文件(不含子目录)
            $filesInDir = Get-ChildItem -Path $resolved.Path -File
            $fileList += $filesInDir.FullName
        } else {
            # 若为文件,直接添加绝对路径
            $fileList += $resolved.Path
        }
    }
}
# 可选:去重并排序,避免重复处理
$fileList = $fileList | Select-Object -Unique | Sort-Object

这段代码的作用:

  • 用Resolve-Path处理通配符和相对路径,转换为绝对路径
  • 自动区分文件和目录:目录则遍历内部文件,文件则直接加入列表
  • 对无效路径输出警告并跳过
  • 可选去重排序,提升批量处理的稳定性

3. 适配PowerShell v5.1的注意事项

  • Resolve-Path和Get-ChildItem在v5.1中的行为与最新版一致,无需额外调整
  • 若需处理权限问题,可将-ErrorAction SilentlyContinue改为-ErrorAction Stop并添加异常捕获,但静默跳过更适合批量处理场景

4. 完整参数块示例

更新后的param块如下:

[CmdletBinding()]
param(
  [Parameter()][Boolean]$loop = $true,
  [Parameter()][Boolean]$twoPass = $true,
  [Parameter()][Int]$height = -1,
  [Parameter()][Int]$width = 1280,
  [Parameter()][Int]$quality = 80,
  [Parameter()][Int]$samplerate = 48000,
  [Parameter()][Int]$compression = 6,
  [Parameter()][Int]$giType = 1,
  [Parameter()][Int]$fps = 24,
  [Parameter()][Int]$bitrate = 320,
  [Parameter()][String]$preset = "picture",
  [Parameter()][Switch]$lossless = $false,
  [Parameter(Position = 0, Mandatory = $true)][String]$subcmd = "",
  [Parameter(Position = 1, Mandatory = $true, ValueFromRemainingArguments = $true)]
  [String[]]$InputPaths
)

内容的提问来源于stack exchange,提问作者tetratheta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 07:25:38