Skip to content

让ai写了一键合并的ps脚本,脚本和exe放在扫描的教材根目录即可一键合并 #183

@noame19

Description

@noame19
<#
run_merge_in_folders.ps1
用途:
  - 递归查找形如 *.pdf.1/*.pdf.2/... 的分片文件所在目录
  - 在每个这样的目录以该目录为工作目录启动同目录下的 mergePDFs-windows-amd64.exe(等同于双击)
参数:
  -RootDir <string>    : 要扫描的根目录,默认脚本所在目录
  -Force               : 强制运行即使目标合并文件已存在
  -DryRun              : 仅列出将要在那些目录运行,不实际执行 exe
  -SkipIfAllOutputExist: 如果该目录中所有分片的目标输出都已存在则跳过该目录(默认开启)
示例:
  powershell -ExecutionPolicy Bypass -File .\run_merge_in_folders.ps1
  powershell -ExecutionPolicy Bypass -File .\run_merge_in_folders.ps1 -RootDir "D:\教材PDF" -DryRun
#>

param(
    [string]$RootDir = $PSScriptRoot,
    [switch]$Force,
    [switch]$DryRun,
    [switch]$SkipIfAllOutputExist = $true
)

# exe 文件(假设和脚本同目录)
$ExePath = Join-Path $PSScriptRoot 'mergePDFs-windows-amd64.exe'
if (-not (Test-Path $ExePath) -and -not $DryRun) {
    Write-Error "找不到: $ExePath 。请把 mergePDFs-windows-amd64.exe 放到脚本同目录,或修改脚本中的 \$ExePath"
    exit 1
}

Write-Host "根目录: $RootDir"
Write-Host "合并程序: $ExePath"
if ($Force) { Write-Host "模式: 强制运行(覆盖)" }
if ($DryRun) { Write-Host "模式: DryRun(仅列出目录,不执行)" }
if ($SkipIfAllOutputExist) { Write-Host "已启用: 若目录中所有目标输出已存在则跳过该目录" }

# 找到所有 *.pdf.<数字> 文件,按目录分组
$parts = Get-ChildItem -Path $RootDir -Recurse -File -ErrorAction SilentlyContinue |
         Where-Object { $_.Name -match '\.pdf\.\d+$' }

if (-not $parts) {
    Write-Host "未找到任何 '*.pdf.<数字>' 分片文件,退出。"
    exit 0
}

# 以目录为单位分组
$dirs = $parts | Group-Object -Property DirectoryName

foreach ($g in $dirs) {
    $dir = $g.Name
    # 在该目录内找出不同的 baseName(例如 'xxx.pdf' 来自 'xxx.pdf.1')
    $baseNames = $g.Group | ForEach-Object {
        # BaseName for "aaa.pdf.1" returns "aaa.pdf"
        $_.BaseName
    } | Sort-Object -Unique

    # 预期输出文件(每个 baseName 本身就是 "xxx.pdf")
    $expectedOutputs = $baseNames | ForEach-Object { Join-Path $dir $_ }

    $allExist = $true
    foreach ($out in $expectedOutputs) {
        if (-not (Test-Path $out)) { $allExist = $false; break }
    }

    if ($SkipIfAllOutputExist -and $allExist -and -not $Force) {
        Write-Host "跳过目录(所有目标输出已存在): $dir"
        continue
    }

    Write-Host ""
    Write-Host "========"
    Write-Host "将对目录运行 exe: $dir"
    Write-Host "  分片基名数量: $($baseNames.Count)"
    foreach ($b in $baseNames) { Write-Host "   - $b" }

    if ($DryRun) {
        Write-Host "(DryRun) 不执行 exe:继续下一个目录。"
        continue
    }

    # 以该目录作为工作目录启动 exe(等同于在目录中双击 exe)
    try {
        Write-Host "启动合并程序(在该目录为工作目录)..."
        $proc = Start-Process -FilePath $ExePath -WorkingDirectory $dir -NoNewWindow -Wait -PassThru

        if ($proc -and $proc.ExitCode -eq 0) {
            Write-Host "✅ 合并进程完成(ExitCode 0):$dir"
        } elseif ($proc) {
            Write-Warning "❗ 合并进程在目录 $dir 返回代码 $($proc.ExitCode)。请检查该目录下 exe 的输出或错误。"
        } else {
            Write-Warning "❗ 无法获取进程信息(可能已启动但无法读取 ExitCode)。"
        }
    } catch {
        Write-Error "在目录 $dir 启动 exe 时出现异常: $_"
    }
}

Write-Host ""
Write-Host "全部目录处理完毕。"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions