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

在PowerShell中复制文件和文件夹时显示进度的实现方案

解决方案

方案1:用Robocopy(首推,性能拉满)

Robocopy是Windows自带的硬核复制工具,天生为大文件/海量文件场景优化,支持多线程,还能轻松配置成只显示进度、不刷一堆文件列表,完美匹配你的需求。

命令示例

$sourcePath = "F:\Music\W\Whitlams"
$kpath = "K:\W\Whitlams"
robocopy $sourcePath $kpath /E /COPYALL /R:0 /W:0 /MT:8 /NFL /NDL /TEE

参数拆解:

  • /E:递归复制所有子目录(包括空目录),和Copy-Item -Recurse效果一致
  • /COPYALL:复制文件所有属性(权限、时间戳等),替代Copy-Item -Force的作用
  • /R:0 /W:0:复制失败直接跳过,不重试不等待,避免卡壳
  • /MT:8:开8线程复制(最多能开128线程,可根据机器性能调整,大文件多线程复制速度提升明显)
  • /NFL /NDL:不显示任何文件、目录的名称列表,控制台保持干净整洁
  • /TEE:实时输出复制统计(已复制的文件数、字节数、剩余时间估算),能直观看到整体进度

方案2:自定义PowerShell函数(纯Cmdlet实现全局进度条)

如果偏爱纯PowerShell原生命令的方式,可以自己写个函数,先算出源文件总大小,复制时实时更新全局进度,全程不刷文件列表。

函数代码

function Copy-WithTotalProgress {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string]$SourcePath,
        [Parameter(Mandatory=$true)]
        [string]$DestinationPath
    )

    # 先扫描源目录,获取所有文件和总大小
    $allFiles = Get-ChildItem -Path $SourcePath -File -Recurse -Force
    $totalBytes = ($allFiles | Measure-Object -Property Length -Sum).Sum
    $copiedBytes = 0

    # 创建目标根目录(不存在则新建)
    if (-not (Test-Path -Path $DestinationPath)) {
        New-Item -Path $DestinationPath -ItemType Directory -Force | Out-Null
    }

    # 逐个复制文件,更新全局进度
    foreach ($file in $allFiles) {
        # 拼接目标文件路径
        $destFile = $file.FullName.Replace($SourcePath, $DestinationPath)
        # 确保目标文件的父目录存在
        $destDir = Split-Path -Path $destFile -Parent
        if (-not (Test-Path -Path $destDir)) {
            New-Item -Path $destDir -ItemType Directory -Force | Out-Null
        }
        # 复制文件(逻辑和Copy-Item -Force一致)
        Copy-Item -Path $file.FullName -Destination $destFile -Force
        # 累加已复制大小,计算进度百分比
        $copiedBytes += $file.Length
        $percentComplete = [math]::Round(($copiedBytes / $totalBytes) * 100, 2)
        # 更新进度条,仅显示全局进度,不输出文件信息
        Write-Progress -Activity "正在复制文件" -Status "已完成 $percentComplete%" -PercentComplete $percentComplete
    }

    # 复制完成后关闭进度条
    Write-Progress -Activity "正在复制文件" -Completed -Status "复制完成"
}

使用方式

$sourcePath = "F:\Music\W\Whitlams"
$kpath = "K:\W\Whitlams"
Copy-WithTotalProgress -SourcePath $sourcePath -DestinationPath $kpath

注意点

  • 前期会先遍历源目录计算总大小,超大目录可能需要几秒,但复制过程性能和Copy-Item几乎无差,不会拖慢跨工作组传输速度。
  • 全程只有一个进度条在控制台顶部,不会刷出大量文件列表,保持界面整洁。

为啥你之前的方法不好用?

  • Write-Progress没法直接配合Copy-Item -Recurse使用,因为Copy-Item是一次性批量执行,无法获取中间的进度数据。
  • Start-BitsTransfer原本是为后台异步传输设计的,控制台内的进度更新机制不稳定,且默认会列出文件,不符合你要的简洁需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 04:07:11