【问题标题】:Process bar Powershell进程栏 Powershell
【发布时间】:2021-02-16 22:52:26
【问题描述】:

我需要将硬盘复制到我的 NAS,但我只想要图像和视频,同时保留文件夹和子文件夹结构。

我有这段代码可以工作,但想添加一个进度条。

PS : 我是 powershell 的新手,所以我很想有一些建议或方法来改进我的代码,使其更加可靠,这样它就不会在复制过程中损坏或出现问题(我有大约 90GB 的视频和照片要复制)。

提前谢谢你!

我的代码:

$sourcePath = 'D:\Users\Dave'
$destPath = 'Z:\Dave Dimov\Photos\HDD 1'
    
Get-ChildItem $sourcePath -Recurse -Include '*.png', '*.jpg', '*.jpeg' , '*.mov' , '*.mp4' | Foreach-Object ` {
    
    $destDir = Split-Path ($_.FullName -Replace [regex]::Escape($sourcePath), $destPath)

    if (!(Test-Path $destDir))
    
{
New-Item -ItemType directory $destDir
}

Copy-Item  $_ -Destination $destDir

}

【问题讨论】:

  • 使用robocopy ...它专为您所描述的而设计。 [咧嘴一笑]
  • 谢谢,会检查一下,看看我能做些什么。如果它有效,将更新代码,否则我会再次陷入困境,哈哈
  • 不客气!很高兴能帮上一点忙……[咧嘴一笑]

标签: powershell


【解决方案1】:

根据Trevor Sullivans "Copy-WithProgress" 的回答,这可能对你有用。

$sourcePath = 'D:\Users\Dave'
$destPath = Test-Path -Path 'Z:\Dave Dimov\Photos\HDD 1'
    if(!$destPath){New-Item -ItemType directory $destDir}
    
$DIRe = Get-ChildItem $sourcePath -Filter '*.png', '*.jpg', '*.jpeg' , '*.mov' , '*.mp4' -Recurse 
Copy-WithProgress $DIRe -Destination $destPath -Verbose



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;
#>

【讨论】:

    【解决方案2】:

    这对我现在有用:

        function Copy-WithProgress {
        [CmdletBinding()]
        param (
                [Parameter(Mandatory = $true)]
                [string] $Source
            , [Parameter(Mandatory = $true)]
                [string] $Destination
            , [int] $Gap = 0
            , [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 =  '*.png *.jpg *.jpeg *.mov *.mp4 /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
    }
    
    $sourcePath = 'D:\Users\Dave'
    $destPath = 'Z:\Dave Dimov\Photos\HDD 1'
    
    Copy-WithProgress -Source $srcBase -Destination $dstBase -Verbose | ROBOCOPY $dstBase $dstBase /S /MOVE | Out-File -FilePath C:\Users\DaveD\Desktop\LOG.log
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-08
      • 2011-04-27
      • 2014-09-24
      • 2014-10-22
      • 1970-01-01
      相关资源
      最近更新 更多