Saltar al contenido

Barra de progreso personalizada de RoboCopy en PowerShell

Queremos darte la mejor respuesta que hemos encontrado por todo internet. Esperamos que te sirva de ayuda y si puedes compartir algún detalle que nos pueda ayudar a mejorar hazlo con total libertad.

Solución:

Escribí una función de PowerShell llamada Copy-WithProgress que logrará lo que busca. Como dijiste específicamente que estabas usando robocopy, construí una función de PowerShell que encapsula la funcionalidad robocopy (al menos, partes de ella).

Permítame mostrarle cómo funciona. También grabé y publiqué un video de YouTube que demuestra cómo está diseñada para funcionar la función e invoca una ejecución de prueba.

La función se divide en regiones:

  • Parámetros de robocopy comunes
  • Puesta en escena (donde se calcula el tamaño del trabajo de robocopy)
  • Copiar (donde se inicia el trabajo de copia automática)
  • Barra de progreso (donde se monitorea el progreso de robocopy)
  • Salida de función (donde se generan algunas estadísticas útiles, para usar en el resto de su secuencia de comandos)

Hay varios parámetros en la función.

  • Fuente: El directorio de origen
  • Destino: El directorio de destino
  • Brecha: La “brecha entre paquetes” en milisegundos admitida por robocopy, que ralentiza artificialmente la copia, para realizar pruebas)
  • ReportGap: El intervalo (en milisegundos) para comprobar el progreso de la copia automática

En la parte inferior del script (después de la definición de la función), hay un ejemplo completo de cómo llamarlo. Debería funcionar en su computadora, ya que todo es variable. Hay cinco pasos:

  1. Genera un directorio de origen aleatorio
  2. Genera un directorio de destino
  3. Llama a Copy-WithProgress función
  4. Cree algunos archivos de origen adicionales (para emular los cambios a lo largo del tiempo)
  5. Llama a Copy-WithProgress funcionar de nuevo, y validar que solo se replican los cambios

Aquí hay una captura de pantalla de cómo se ve la salida de la función. Puedes dejar el -Verbose parámetro, si no desea toda la información de depuración. A PSCustomObject es devuelto, por la función, que le dice:

  1. Cuantos bytes se copiaron
  2. Cuantos archivos se copiaron

Función Copy-WithProgress PowerShell

Aquí hay una captura de pantalla del Barra de progreso de PowerShell en PowerShell ISE y en el host de la consola de PowerShell.

Barra de progreso de PowerShell (ISE)

Barra de progreso de PowerShell (host de consola)

Aquí está el código:

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 = '0temp1 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) 

# 1. TESTING: Generate a random, unique source directory, with some test files in it
$TestSource = '01' -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 = '01' -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;

Estas soluciones son excelentes, pero una forma rápida y fácil de obtener un progreso flotante para todos los archivos fácilmente es la siguiente:

robocopy   /MIR /NDL /NJH /NJS | %$data = $_.Split([char]9); if("$($data[4])" -ne "")  $file = "$($data[4])" ;Write-Progress "Percentage $($data[0])" -Activity "Robocopy" -CurrentOperation "$($file)"  -ErrorAction SilentlyContinue; 

¿Es absolutamente necesario utilizar robocopy?

De lo contrario, puede llamar al código en este hilo para cada archivo: Progreso durante la copia de archivo grande (¿Copiar elemento y escribir progreso?)

Alternativamente, use el interruptor / L de robocopy como se llama desde powershell para obtener la lista de archivos que robocopy habría copiado y use un bucle for-each para ejecutar cada archivo a través de esa función de copia.

Incluso podría anidar comandos de progreso de escritura para poder informar "archivo x de y - XX% completo"

Algo como esto debería funcionar, necesita un poco de trabajo para los subdirectorios (sospecho que algo más que agregar -recurse al comando gci), pero lo pondrá en la dirección correcta.

NOTA: Estoy escribiendo esto en un teléfono, el código aún no se ha probado ...

function Copy-File 
param( [string]$from, [string]$to)
$ffile = [io.file]::OpenRead($from)
$tofile = [io.file]::OpenWrite($to)
Write-Progress `
    -Activity ("Copying file " + $filecount + " of " + $files.count) `
    -status ($from.Split("")

$srcdir = "C:Source;
$destdir = "C:Dest";
[int]$filecount = 0;
$files = (Get-ChildItem $SrcDir | where-object -not ($_.PSIsContainer));
$files|foreach($_)
$filecount++
if ([system.io.file]::Exists($destdir+$_.name))
                [system.io.file]::Delete($destdir+$_.name)
                Copy-File -from $_.fullname -to ($destdir+$_.name)
;

Personalmente, uso este código para copias pequeñas en una memoria USB, pero uso robocopy en un script de PowerShell para copias de seguridad de PC.

Más adelante puedes encontrar las ilustraciones de otros gestores de proyectos, tú asimismo eres capaz mostrar el tuyo si lo deseas.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags : /

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *