PowerShell 中的自定义 RoboCopy 进度条 [英] Custom RoboCopy Progress Bar in PowerShell
问题描述
我对每天从服务器复制大量文件的 PowerShell 脚本感兴趣,并且我对实现类似的控制台进度条很感兴趣
I'm interested in a PowerShell script that copies a large amount of files from a server daily and I'm interested in implementing a in-console progress bar like
文件复制状态 - XX% 完成.
where XX%
更新在同一行而不是换行之后的换行.我决定暂时使用 RoboCopy.我目前有
where XX%
updates on the same line instead of newline after newline. I've decided to go with RoboCopy for now. I've currently got
ROBOCOPY 'C:\Users\JMondy\Desktop\Sample1' 'C:\Users\JMondy\Desktop\Sample2' ./E/IS/NFL/NJH
ROBOCOPY 'C:\Users\JMondy\Desktop\Sample1' 'C:\Users\JMondy\Desktop\Sample2' . /E /IS /NFL /NJH
下一步是什么?
推荐答案
我编写了一个名为 Copy-WithProgress
的 PowerShell 函数,它将实现您的目标.由于您明确声明您使用的是 robocopy,因此我构建了一个 PowerShell 函数来封装 robocopy 功能(至少是其中的一部分).
I wrote a PowerShell function called Copy-WithProgress
that will achieve what you are after. Since you specifically stated that you were using robocopy, I built a PowerShell function that encapsulates the robocopy functionality (at least, parts of it).
请允许我向您展示它是如何工作的.我还录制并发布了一个 YouTube 视频,演示了该功能的工作原理,并调用测试运行.
Allow me to show you how it works. I've also recorded and posted a YouTube video demonstrating how the function is designed to work, and invoking a test run.
功能分为区域:
- 常见的 robocopy 参数
- 暂存(计算 robocopy 作业大小)
- 复制(robocopy 工作开始的地方)
- 进度条(监控机器复制进度的地方)
- 函数输出(输出一些有用的统计数据,用于脚本的其余部分)
该函数有几个参数.
- 源:源目录
- 目标:目标目录
- Gap:robocopy支持的以毫秒为单位的数据包间隙",人为减慢复制速度,用于测试)
- ReportGap:检查 robocopy 进度的间隔(以毫秒为单位)
- Source: The source directory
- Destination: The destination directory
- Gap: The "inter-packet gap" in milliseconds supported by robocopy, which artificially slows down the copy, for testing)
- ReportGap: The interval (in milliseconds) to check on robocopy progress
在脚本的底部(在函数定义之后),是如何调用它的完整示例.它应该可以在您的计算机上运行,因为一切都是可变的.有五个步骤:
At the bottom of the script (after the function definition), is a complete example of how to call it. It should work on your computer, since everything is variable-ized. There are five steps:
- 生成随机源目录
- 生成目标目录
- 调用
Copy-WithProgress
函数 - 创建一些额外的源文件(以模拟随时间的变化)
- 再次调用
Copy-WithProgress
函数,并验证仅复制更改
- Generate a random source directory
- Generate a destination directory
- Call the
Copy-WithProgress
function - Create some additional source files (to emulate changes over time)
- Call the
Copy-WithProgress
function again, and validate only changes are replicated
这是函数输出的屏幕截图.如果您不想要所有调试信息,您可以省略 -Verbose
参数.函数返回一个 PSCustomObject
,它告诉你:
Here is a screenshot of what the function's output looks like. You can leave off the -Verbose
parameter, if you do not want all of the debugging information. A PSCustomObject
is returned, by the function, which tells you:
- 复制了多少字节
- 复制了多少文件
这是 PowerShell ISE 中 PowerShell 进度条 和 PowerShell 控制台主机的屏幕截图.
Here is a screenshot of the PowerShell Progress Bar in the PowerShell ISE, and the PowerShell Console Host.
代码如下:
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 中的自定义 RoboCopy 进度条的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!