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 a source. This way a batch operation however stops 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