This is an old revision of the document!

Recursively download directory tree with custom error handling

The simplest way to download a directory tree is by using Session.GetFiles, providing path to a root of the tree as source. This way the batch operation however stop on any error. If you need to use a custom error handling, for example to ignore any error and just continue, you need to implement walking the tree explicitly.

This example shows a basic implementation that outputs any errors encountered and continues.

Advertisement

The example uses WinSCP .NET assembly from a PowerShell script. If you have another preferred language, you can easily translate it.

param (
    [Parameter(Mandatory)]
    $sessionUrl = "sftp://user:mypassword;fingerprint=ssh-rsa-xx-xx-xx@example.com/",
    [Parameter(Mandatory)]
    $remotePath,
    [Parameter(Mandatory)]
    $localPath
)
 
function DownloadDirectory ($session, $localPath, $remotePath)
{
    Write-Host ("Downloading directory {0} ..." -f $remotePath)
 
    try
    {
        $directoryInfo = $session.ListDirectory($remotePath)
 
        foreach ($fileInfo in $directoryInfo.Files)
        {
            $remoteFilePath = ($remotePath + "/" + $fileInfo.Name) 
            
            if ($fileInfo.IsDirectory)
            {
                # Skip references to current and parent directories
                if (($fileInfo.Name -ne ".") -and
                    ($fileInfo.Name -ne ".."))
                {
                    # Recurse into subdirectories
                    $localDirPath = ($localPath + "\" + $fileInfo.Name)
 
                    # Create local subdirectory, if it does not exist yet
                    if (!(Test-Path $localDirPath))
                    {
                        New-Item $localDirPath -ItemType directory | Out-Null
                    }
 
                    DownloadDirectory $session $localDirPath $remoteFilePath
                }
            }
            else
            {
                Write-Host ("Downloading file {0}..." -f $remoteFilePath)
                # Download file
                $transferResult = $session.GetFiles($remoteFilePath, ($localPath + "\"))
 
                # Did the download succeded?
                if (!$transferResult.IsSuccess)
                {
                    # Print error (but continue with other files)
                    Write-Host ("Error downloading file {0}: {1}" -f $remoteFilePath, $transferResult.Failures[0].Message)
                }
            }
        }
    }
    catch [Exception]
    {
        Write-Host ("Error downloading directory {0}: {1}" -f $remotePath, $_.Exception.Message)
    }
}
 
try
{
    # Load WinSCP .NET assembly
    Add-Type -Path "WinSCPnet.dll"
 
    # Setup session options from URL
    $sessionOptions = New-Object WinSCP.SessionOptions
    $sessionOptions.ParseUrl($sessionUrl);
 
    $session = New-Object WinSCP.Session
    $session.SessionLogPath = "session.log"
    
    try
    {
        # Connect
        $session.Open($sessionOptions)
        
        # Start recursion
        DownloadDirectory $session $localPath $remotePath
    }
    finally
    {
        # Disconnect, clean up
        $session.Dispose()
    }
 
    exit 0
}
catch [Exception]
{
    Write-Host $_.Exception.Message
    exit 1
}

Advertisement

Last modified: by martin