Skip to main content

PowerShell function that serves as a wrapper for the Robocopy (Robust Copy) command utility.

function Copy-Robust
{
    [CmdletBinding()]
    param(
        # The source path to copy files from.
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]
        $SourcePath,

        # The destination path to copy files to.
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]
        $DestinationPath,

        # Directories to exclude from copying.
        [Parameter()]
        [string[]]
        $ExcludeDirectories = $null,

        # Files to exclude from copying.
        [Parameter()]
        [string[]]
        $ExcludeFiles = $null,

        # Additional arguments to pass to robocopy
        [Parameter()]
        [string[]]
        $AdditionalArguments = @(),

        # Execute robocopy under the specified user credentials.
        [Parameter()]
        [PSCredential]
        $Credential = $null,

        # If present, no copy operations will be performed.
        [Parameter()]
        [switch]
        $DryRun
    )

    Write-Host "Copying '$SourcePath' to '$DestinationPath'" -ForegroundColor Cyan

    $defaultParams = @('/MIR', '/NP', '/NFL', '/NDL', '/NJS', '/NC', '/NS') # Mirror and be quiet :-)

    if ($DryRun)
    {
        $defaultParams += '/L'
    }

    $excludeDirParams = @()
    if ($ExcludeDirectories -ne $null)
    {
        $excludeDirParams = @("/XD")
        $excludeDirParams += $ExcludeDirectories
    }

    $excludeFileParams = @()
    if ($ExcludeFiles -ne $null)
    {
        $excludeFileParams = @("/XF")
        $excludeFileParams += $ExcludeFiles
    }

    $exitCode = 0

    if ($Credential -ne $null)
    {
        $argumentList = @()
        $argumentList += $SourcePath
        $argumentList += $DestinationPath
        $argumentList += $defaultParams
        $argumentList += $AdditionalArguments
        $argumentList += $excludeDirParams
        $argumentList += $excludeFileParams

        $proc = Start-Process robocopy -Credential $credential -PassThru -Wait -WindowStyle Hidden -ArgumentList $argumentList
        $proc.WaitForExit()
        $exitCode = $proc.ExitCode
    }
    else
    {
        & "robocopy" $SourcePath $DestinationPath $defaultParams $AdditionalArguments $excludeDirParams $excludeFileParams
        $exitCode = $LASTEXITCODE
    }

    Write-Host ("Robocopy finished with exit code {0}" -f $exitCode) -ForegroundColor Yellow
}

#
# Example usage:
#

$splat = @{
    SourcePath         = 'C:\project\bin\Release'
    DestinationPath    = 'C:\tmp\robocopy-tests'
    ExcludeDirectories = '.vs', '.git'
    ExcludeFiles       = '*.suo', '*.user', 'project.json', '*.lock.json'
    DryRun             = $false
}

Copy-Robust @splat