powershellftpwinscpwinscp-net

Transferring only selected set of subfolders and not files in root folder using WinSCP


I have the following in a ps1 script and I am connecting over FTP using WinsCP to a Nitrado server with the goal of copying the folder called backups and the contents over to my pc. The issue I face is when I run the following it just returns the whole of the minecraftbukkit folder almost as if it ignores the mask other than '*' and just returns it all. I have tried using a mask of "backups/" however this then returns nothing and in the log output it says File "/minecraftbukkit" excluded from transfer.

I have tried this on my personal Linux server and it seemed to work so is this some issue based on the nitrado service? Or possibly their Linux server is missing a feature that is needed or something. I am open to any suggestions on how to make this work as intended. Thanks in advance.

try
{
    # Load WinSCP .NET assembly
     Add-Type -Path "D:\Users\username\Downloads\Minecraft stuff\Scripts\WinSCPnet.dll"
    
    $folderPath = 'D:\Users\username\Downloads\Minecraft stuff\test'
    $folderPath2 = '/minecraftbukkit'
    
    # Session.FileTransferProgress event handler
    
    function FileTransferProgress
    {
        param($e)
 
        # New line for every new file
        if (($script:lastFileName -ne $Null) -and
            ($script:lastFileName -ne $e.FileName))
        {
            Write-Host
        }
 
        # Print transfer progress
        Write-Host -NoNewline ("`r{0} ({1:P0})" -f $e.FileName, $e.FileProgress)
 
        # Remember a name of the last file reported
        $script:lastFileName = $e.FileName
    }

    $script:lastFileName = $Null
    
    # Setup session options
    $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
        Protocol = [WinSCP.Protocol]::ftp
        HostName = "hostname"
        PortNumber = 21
        UserName = "username"
        Password = "password"
    }
 
    $session = New-Object WinSCP.Session

    try
    {
        # Will continuously report progress of transfer
        $session.add_FileTransferProgress( { FileTransferProgress($_) } )
        $session.SessionLogPath = "sessionlog.txt"
        # Connect
        $session.Open($sessionOptions)

        # Upload files
        $transferOptions = New-Object WinSCP.TransferOptions
        $transferOptions.TransferMode = [WinSCP.TransferMode]::Binary
        $transferOptions.FileMask = "backups/"
 
        [array]$transferResult += $session.GetFiles($folderPath2, $folderPath , $False, $transferOptions)
        
        # Throw on any error
        $transferResult.Check()
 
        # Print results
        foreach ($transfer in $transferResult.Transfers)
        {
            Write-Host "Upload of $($transfer.FileName) succeeded"
        }

        foreach ($transfer in $transferResult.Failures)
        {
            Write-Host "Upload of $($transfer.FileName) Failed"
        }
    }
    finally
    {
        # Disconnect, clean up
        $session.Dispose()
    }
 
    exit 0
}
catch
{
    Write-Host "Error: $($_.Exception.Message)"
    exit 1
}

Log (omitted beginning and usernames for privacy):

--------------------------------------------------------------------------
< 2021-11-16 12:04:38.845 230 User logged in
> 2021-11-16 12:04:38.845 SYST
< 2021-11-16 12:04:38.860 215 UNIX Type: L8
> 2021-11-16 12:04:38.860 FEAT
< 2021-11-16 12:04:38.874 211-Features:
< 2021-11-16 12:04:38.874  AUTH TLS
< 2021-11-16 12:04:38.874  CCC
< 2021-11-16 12:04:38.875  CLNT
< 2021-11-16 12:04:38.875  EPRT
< 2021-11-16 12:04:38.875  EPSV
< 2021-11-16 12:04:38.875  HOST
< 2021-11-16 12:04:38.875  LANG zh-CN;zh-TW;bg-BG;en-US;es-ES;fr-FR;it-IT;ja-JP;ko-KR;ru-RU
< 2021-11-16 12:04:38.875  MDTM
< 2021-11-16 12:04:38.875  MFF modify;UNIX.group;UNIX.mode;
< 2021-11-16 12:04:38.875  MFMT
< 2021-11-16 12:04:38.875  MLST modify*;perm*;size*;type*;unique*;UNIX.group*;UNIX.groupname*;UNIX.mode*;UNIX.owner*;UNIX.ownername*;
< 2021-11-16 12:04:38.875  PBSZ
< 2021-11-16 12:04:38.875  PROT
< 2021-11-16 12:04:38.876  REST STREAM
< 2021-11-16 12:04:38.876  SIZE
< 2021-11-16 12:04:38.876  SSCN
< 2021-11-16 12:04:38.876  TVFS
< 2021-11-16 12:04:38.876  UTF8
< 2021-11-16 12:04:38.876 211 End
> 2021-11-16 12:04:38.876 CLNT WinSCP-release-5.19.2
< 2021-11-16 12:04:38.891 200 OK
> 2021-11-16 12:04:38.891 OPTS UTF8 ON
< 2021-11-16 12:04:38.909 200 UTF8 set to on
< 2021-11-16 12:04:38.909 Script: Connected
. 2021-11-16 12:04:38.910 Connected
. 2021-11-16 12:04:38.910 --------------------------------------------------------------------------
. 2021-11-16 12:04:38.910 Using FTP protocol.
. 2021-11-16 12:04:38.910 Doing startup conversation with host.
< 2021-11-16 12:04:38.910 Script: Starting the session...
> 2021-11-16 12:04:38.910 PWD
< 2021-11-16 12:04:38.923 257 "/" is the current directory
. 2021-11-16 12:04:38.924 Getting current directory name.
. 2021-11-16 12:04:38.924 Startup conversation with host finished.
< 2021-11-16 12:04:38.924 Script: Session started.
< 2021-11-16 12:04:38.924 Script: Active session: [1] 
> 2021-11-16 12:04:39.643 Script: pwd
< 2021-11-16 12:04:39.644 Script: /
> 2021-11-16 12:04:39.716 Script: get  -nopermissions -preservetime -transfer="binary" -filemask="backups/"  -- "/minecraftbukkit" "D:\Users\username\Downloads\Minecraft stuff\test"
. 2021-11-16 12:04:39.716 Listing file "/minecraftbukkit".
. 2021-11-16 12:04:39.717 Retrieving file information...
> 2021-11-16 12:04:39.717 MLST /minecraftbukkit
< 2021-11-16 12:04:39.731 250-Start of list for /minecraftbukkit
< 2021-11-16 12:04:39.732  modify=20211112092756;perm=flcdmpe;type=dir;unique=10304U4064951C;UNIX.group=11257;UNIX.groupname=11257;UNIX.mode=0700;UNIX.owner=6258;UNIX.ownername=; /minecraftbukkit
< 2021-11-16 12:04:39.732 250 End of list
. 2021-11-16 12:04:39.732  modify=20211112092756;perm=flcdmpe;type=dir;unique=10304U4064951C;UNIX.group=11257;UNIX.groupname=11257;UNIX.mode=0700;UNIX.owner=6258;UNIX.ownername=; /minecraftbukkit
. 2021-11-16 12:04:39.732 Retrieving file information successful
. 2021-11-16 12:04:39.733 minecraftbukkit;D;0;2021-11-12T09:27:56.000Z;3;"" [0];"11257" [0];rwx------;0
. 2021-11-16 12:04:39.733 Copying 1 files/directories to local directory "D:\Users\username\Downloads\Minecraft stuff\" - total size: 0
. 2021-11-16 12:04:39.733   PrTime: Yes; PrRO: No; Rght: rw-r--r--; PrR: No (No); FnCs: N; RIC: 0100; Resume: S (102400); CalcS: Yes; Mask: test
. 2021-11-16 12:04:39.733   TM: B; ClAr: No; RemEOF: No; RemBOM: No; CPS: 0; NewerOnly: No; EncryptNewFiles: Yes; ExcludeHiddenFiles: No; ExcludeEmptyDirectories: No; InclM: backups/; ResumeL: 0
. 2021-11-16 12:04:39.733   AscM: *.*html; *.htm; *.txt; *.php; *.php3; *.cgi; *.c; *.cpp; *.h; *.pas; *.bas; *.tex; *.pl; *.js; .htaccess; *.xtml; *.css; *.cfg; *.ini; *.sh; *.xml
. 2021-11-16 12:04:39.733 File "/minecraftbukkit" excluded from transfer
* 2021-11-16 12:04:39.733 (ESkipFile) 
. 2021-11-16 12:04:39.733 Copying finished: Transferred: 0, Elapsed: 0:00:00, CPS: 0/s
> 2021-11-16 12:04:39.826 Script: exit
. 2021-11-16 12:04:39.826 Script: Exit code: 0
. 2021-11-16 12:04:39.830 Disconnected from server

In terms of folder structure this is it just a regular bukkit layout and I am trying to pull the backups folder as shown:

enter image description here


Solution

  • If you want to download backups specifically, do it explicitly:

    $folderPath2 = '/minecraftbukkit/backups/*'
    

    If your point was to make the "filemask" variable, your problem is that your are giving WinSCP conflicting masks. You are telling it to download everything that has name minecraftbukkit and backups at the same time. So it does not download anything.

    If you want to tell WinSCP to apply the mask to files in minecraftbukkit and not to the minecraftbukkit directly, you need to select files in the files, not the folder itself, by adding /*:

    $folderPath2 = '/minecraftbukkit/*'
    

    As the documentation for the remotePath parameter says:

    Full path to remote directory followed by slash and wildcard to select files or subdirectories to download. To download all files in a directory, use mask *.


    It's more complicated if you want to do recursive transfers. Then you need to use path mask, like:

    */plugins/*;*/plugins/*/*;*/backups/*;*/backups/*/*
    

    But you will need to enable ExcludeEmptyDirectories to avoid "downloading" folders that contains no matches files. Note that WinSCP will iterate all folders unnecessarily anyway.


    Better option might be to select the folders (what implicitly includes all subfolders and contained files), but exclude all files directly in the root folder, like:

    plugins/; backups/ | /minecraftbukkit/*
    

    Since WinSCP 5.20.1, you can use masks relative to the root of the operation (i.e. /minecraftbukkit):

    plugins/; backups/ | ./*