user3376246
user3376246

Reputation: 423

List of files located in text file to be send as parameter to WinSCP in script mode

I've to create solution that is based on WinSCP and windows batch script. Below are tasks the script has to do:

  1. Save list of files from remote directory, to file located on machine where batch script is run.
  2. Run WinSCP in command mode (/command) using WinSCP script passed as parameter (/script=name_of_script_file.txt) and get files (get command) from previously generated list.

The most important is to get file list, save it and pass names of files located in created file to WinSCP to get them.

How to implement this?

Upvotes: 1

Views: 4225

Answers (1)

Martin Prikryl
Martin Prikryl

Reputation: 202534

There's no easy way to implement this using WinSCP scripting only. It's possible, see the very end of my answer, but it may not be an ideal solution.


Why do you do this in two steps? Why don't you directly download the directory?

winscp.com /command ^
    "option batch abort" ^
    "option confirm off" ^
    "open scp://user:[email protected]/" ^
    "get /path/*" ^
    "exit"

If you really need the list (e.g. for some further processing), you can instead of getting a list of files in the directory, get a list of actually downloaded files.

Enable the XML logging, and get the list from the XML log.

winscp.com /xmllog=log.xml /command ^
    ....

You get a log like:

<?xml version="1.0" encoding="UTF-8"?>
<session xmlns="http://winscp.net/schema/session/1.0" name="user@host" start="2015-01-30T06:45:57.008Z">
  <download>
    <filename value="/path/file1.txt" />
    <destination value="C:\path\file1.txt" />
    <result success="true" />
  </download>
  <download>
    <filename value="/path/file2.txt" />
    <destination value="C:\path\file2.txt" />
    <result success="true" />
  </download>
</session>

If you need a plain-text list, you can use the XSLT to convert it (e.g. download.xslt):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:winscp="http://winscp.net/schema/session/1.0">
    <xsl:output method="text" encoding="UTF-8"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match='winscp:download[winscp:result[@success="true"]]/winscp:filename'>
         <xsl:value-of select="@value"/>
         <xsl:text>&#xa;</xsl:text>
    </xsl:template>
</xsl:stylesheet>

To process it, use any XSLT processor:

  • .NET XslCompiledTransform class, e.g. from PowerShell:

    $xslt = New-Object System.Xml.Xsl.XslCompiledTransform
    $xslt.Load("download.xslt")
    $xslt.Transform("log.xml", "download.txt")
    
  • Libxml2 xsltproc.exe:

    xsltproc.exe download.xslt log.xml
    

And you get:

/path/file1.txt
/path/file2.txt

See Transforming XML Log to Text Output Using XSLT Transformation.


To answer your actual question. If you really insist on getting a file list and downloading files according to it, I suggest you use the WinSCP .NET assembly from a PowerShell script.


If the simple scripting is your preference:

The only way to obtaining a plain text list of remote files reliably, is to use the XML logging to capture an output of the ls scripting command:

winscp.com /xmllog=log.xml /command ^
    "option batch abort" ^
    "option confirm off" ^
    "open scp://user:[email protected]/" ^
    "ls /path" ^
    "exit"

You get a log like:

<?xml version="1.0" encoding="UTF-8"?>
<session xmlns="http://winscp.net/schema/session/1.0" name="user@host" start="2015-01-30T07:08:27.749Z">
  <ls>
    <destination value="/path" />
    <files>
      <file>
        <filename value="." />
        <type value="d" />
        <modification value="2014-07-28T07:06:49.000Z" />
        <permissions value="rwxr-sr-x" />
      </file>
      <file>
        <filename value=".." />
        <type value="d" />
        <modification value="2015-01-23T12:22:44.000Z" />
        <permissions value="rwxr-xr-x" />
      </file>
      <file>
        <filename value="file1.txt" />
        <type value="-" />
        <size value="1306091" />
        <modification value="2015-01-29T23:58:12.000Z" />
        <permissions value="rw-rw-rw-" />
      </file>
      <file>
        <filename value="file2.txt" />
        <type value="-" />
        <size value="88" />
        <modification value="2007-11-17T22:40:43.000Z" />
        <permissions value="rw-r--r--" />
      </file>
    </files>
    <result success="true" />
  </ls>
</session>

Again, use the XSLT to convert the XML log to a plain-text list of files:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:winscp="http://winscp.net/schema/session/1.0">
    <xsl:output method="text" encoding="UTF-8"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match='winscp:file[winscp:type/@value="-"]/winscp:filename'>
         <xsl:value-of select="@value"/>
         <xsl:text>&#xa;</xsl:text>
    </xsl:template>
</xsl:stylesheet>

You get:

file1.txt
file2.txt

To get WinSCP script to download files according to a plain-text list, see scripting example Uploading a list of files. It's for an upload, but just replace the put with the get and reverse an order of arguments to turn it to a download.


Note that the /command parameter does not enter a "command" (scripting?) mode. It's for passing scripting commands on a command line (as used in my answer). You are using a script file (/script). There's no point adding an empty /command parameter to it.

See the documentation of WinSCP scripting command-line parameters.

Upvotes: 4

Related Questions