gpt4 book ai didi

powershell - PowerShell中的自定义RoboCopy进度栏

转载 作者:行者123 更新时间:2023-12-03 10:31:15 28 4
gpt4 key购买 nike

我对每天从服务器复制大量文件的PowerShell脚本感兴趣,并且对实现控制台内进度条(例如
File copy status - XX% complete.
其中XX%在同一行而不是在换行符之后的换行符处更新。我已经决定现在就使用RoboCopy。我目前有
ROBOCOPY 'C:\Users\JMondy\Desktop\Sample1' 'C:\Users\JMondy\Desktop\Sample2' . /E /IS /NFL /NJH
你下一步怎么做?

最佳答案

我编写了一个名为Copy-WithProgress的PowerShell函数,它将实现您所追求的目标。由于您特别声明要使用robocopy,因此我构建了一个PowerShell函数,该函数封装了robocopy功能(至少是其中的一部分)。

请允许我向您展示它的工作原理。我还用recorded and posted a YouTube video演示了该函数的设计原理,并调用了测试运行。

该功能分为几个区域:

  • 常见的robocopy参数
  • 暂存(在其中计算robocopy作业大小)
  • 复制(开始进行robocopy作业的地方)
  • 进度栏(在其中监视自动复制进度)
  • 函数输出(输出一些有用的统计信息,供您在脚本的其余部分中使用)

  • 函数上有几个参数。
  • :源目录
  • 目标:目标目录
  • 间隙:robocopy支持的“数据包间间隔”(以毫秒为单位),这会人为地减慢复制速度,以进行测试)
  • ReportGap :检查robocopy进度的间隔(以毫秒为单位)

  • 在脚本的底部(在函数定义之后),是如何调用它的完整示例。它应该可以在您的计算机上运行,​​因为所有内容都是可变的。分为五个步骤:
  • 生成随机源目录
  • 生成目标目录
  • 调用Copy-WithProgress函数
  • 创建一些其他源文件(以模拟随时间的变化)
  • 再次调用Copy-WithProgress函数,并确认仅复制更改

  • 这是该函数输出的屏幕快照。如果您不希望获得所有调试信息,则可以不使用 -Verbose参数。该函数返回一个 PSCustomObject,它告诉您:
  • 复制了多少字节
  • 复制了多少文件


  • 这是PowerShell ISE中的 PowerShell进度栏和PowerShell控制台主机的屏幕截图。



    这是代码:
    function Copy-WithProgress {
    [CmdletBinding()]
    param (
    [Parameter(Mandatory = $true)]
    [string] $Source
    , [Parameter(Mandatory = $true)]
    [string] $Destination
    , [int] $Gap = 200
    , [int] $ReportGap = 2000
    )
    # Define regular expression that will gather number of bytes copied
    $RegexBytes = '(?<=\s+)\d+(?=\s+)';

    #region Robocopy params
    # MIR = Mirror mode
    # NP = Don't show progress percentage in log
    # NC = Don't log file classes (existing, new file, etc.)
    # BYTES = Show file sizes in bytes
    # NJH = Do not display robocopy job header (JH)
    # NJS = Do not display robocopy job summary (JS)
    # TEE = Display log in stdout AND in target log file
    $CommonRobocopyParams = '/MIR /NP /NDL /NC /BYTES /NJH /NJS';
    #endregion Robocopy params

    #region Robocopy Staging
    Write-Verbose -Message 'Analyzing robocopy job ...';
    $StagingLogPath = '{0}\temp\{1} robocopy staging.log' -f $env:windir, (Get-Date -Format 'yyyy-MM-dd HH-mm-ss');

    $StagingArgumentList = '"{0}" "{1}" /LOG:"{2}" /L {3}' -f $Source, $Destination, $StagingLogPath, $CommonRobocopyParams;
    Write-Verbose -Message ('Staging arguments: {0}' -f $StagingArgumentList);
    Start-Process -Wait -FilePath robocopy.exe -ArgumentList $StagingArgumentList -NoNewWindow;
    # Get the total number of files that will be copied
    $StagingContent = Get-Content -Path $StagingLogPath;
    $TotalFileCount = $StagingContent.Count - 1;

    # Get the total number of bytes to be copied
    [RegEx]::Matches(($StagingContent -join "`n"), $RegexBytes) | % { $BytesTotal = 0; } { $BytesTotal += $_.Value; };
    Write-Verbose -Message ('Total bytes to be copied: {0}' -f $BytesTotal);
    #endregion Robocopy Staging

    #region Start Robocopy
    # Begin the robocopy process
    $RobocopyLogPath = '{0}\temp\{1} robocopy.log' -f $env:windir, (Get-Date -Format 'yyyy-MM-dd HH-mm-ss');
    $ArgumentList = '"{0}" "{1}" /LOG:"{2}" /ipg:{3} {4}' -f $Source, $Destination, $RobocopyLogPath, $Gap, $CommonRobocopyParams;
    Write-Verbose -Message ('Beginning the robocopy process with arguments: {0}' -f $ArgumentList);
    $Robocopy = Start-Process -FilePath robocopy.exe -ArgumentList $ArgumentList -Verbose -PassThru -NoNewWindow;
    Start-Sleep -Milliseconds 100;
    #endregion Start Robocopy

    #region Progress bar loop
    while (!$Robocopy.HasExited) {
    Start-Sleep -Milliseconds $ReportGap;
    $BytesCopied = 0;
    $LogContent = Get-Content -Path $RobocopyLogPath;
    $BytesCopied = [Regex]::Matches($LogContent, $RegexBytes) | ForEach-Object -Process { $BytesCopied += $_.Value; } -End { $BytesCopied; };
    $CopiedFileCount = $LogContent.Count - 1;
    Write-Verbose -Message ('Bytes copied: {0}' -f $BytesCopied);
    Write-Verbose -Message ('Files copied: {0}' -f $LogContent.Count);
    $Percentage = 0;
    if ($BytesCopied -gt 0) {
    $Percentage = (($BytesCopied/$BytesTotal)*100)
    }
    Write-Progress -Activity Robocopy -Status ("Copied {0} of {1} files; Copied {2} of {3} bytes" -f $CopiedFileCount, $TotalFileCount, $BytesCopied, $BytesTotal) -PercentComplete $Percentage
    }
    #endregion Progress loop

    #region Function output
    [PSCustomObject]@{
    BytesCopied = $BytesCopied;
    FilesCopied = $CopiedFileCount;
    };
    #endregion Function output
    }

    # 1. TESTING: Generate a random, unique source directory, with some test files in it
    $TestSource = '{0}\{1}' -f $env:temp, [Guid]::NewGuid().ToString();
    $null = mkdir -Path $TestSource;
    # 1a. TESTING: Create some test source files
    1..20 | % -Process { Set-Content -Path $TestSource\$_.txt -Value ('A'*(Get-Random -Minimum 10 -Maximum 2100)); };

    # 2. TESTING: Create a random, unique target directory
    $TestTarget = '{0}\{1}' -f $env:temp, [Guid]::NewGuid().ToString();
    $null = mkdir -Path $TestTarget;

    # 3. Call the Copy-WithProgress function
    Copy-WithProgress -Source $TestSource -Destination $TestTarget -Verbose;

    # 4. Add some new files to the source directory
    21..40 | % -Process { Set-Content -Path $TestSource\$_.txt -Value ('A'*(Get-Random -Minimum 950 -Maximum 1400)); };

    # 5. Call the Copy-WithProgress function (again)
    Copy-WithProgress -Source $TestSource -Destination $TestTarget -Verbose;

    关于powershell - PowerShell中的自定义RoboCopy进度栏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13883404/

    28 4 0