Why are some WinSCP scripting commands specified in a batch file not executed/failing?

Advertisement

Mixing WinSCP and cmd commands

A common misconception is that in a batch file, you can paste commands as if you typed them in a console window. So after a line that executes winscp.com, you can add WinSCP scripting commands. But that’s not possible. The batch file can contain only commands that you can execute on Windows command prompt – cmd.exe. You cannot directly use sub-commands of those commands (like WinSCP scripting commands).

For example this batch file:

echo Starting WinSCP
winscp.com /log=winscp.log /ini=nul
open sftp://user:password@example.com/
put d:\examplefile.txt 
exit
echo WinSCP finished

It will execute winscp.com, entering an interactive WinSCP scripting prompt. Now WinSCP will wait for you to type your commands (WinSCP is not aware of the batch file). On the other hand cmd.exe (which interprets the batch file), waits for winscp.com to close, before it even checks the following batch file lines. Only after you close winscp.com (e.g. by typing WinSCP exit command), cmd.exe will read the line with the open command. And cmd.exe will fail executing it, as it does not know any open command.

To execute WinSCP commands in a batch file, you need to use /script or /command switches.

  • With /script switch, you need to move your WinSCP commands into a separate text file, e.g. script.txt:
    open sftp://user:password@example.com/
    put d:\examplefile.txt    
    exit
    And execute it from the batch file like:
    echo Starting WinSCP
    winscp.com /script=script.txt /log=winscp.log /ini=nul 
    echo WinSCP finished
  • With /command switch, you can specify the commands directly on WinSCP command-line. Such command-line tends to be too long. Being in a batch file, you can use use new-line escaping using the caret symbol ^ to allow wrapping a long command line to multiple lines for a better readability:
    echo Starting WinSCP
    winscp.com /log=winscp.log /ini=nul /command ^
        "open sftp://user:password@example.com/" ^
        "put d:\examplefile.txt" ^
        "exit"
    echo WinSCP finished

Advertisement

New-line Escaping

Many examples on this site (including the one above), as well as batch file template generated by WinSCP, use new-line escaping using the caret symbol ^ to allow wrapping a long command line to multiple lines for better readability:

winscp.com /log=winscp.log /ini=nul /command ^
    "open sftp://user:password@example.com/" ^
    "get *" ^
    "exit"

When reusing/modifying such script, users frequently find that WinSCP seemingly stops processing the commands in a middle or behaves strangely.

This is commonly caused by an improper syntax of the new-line escaping in the batch file (and as such is not WinSCP issue at all). For the new-line escaping to work as expected in the batch file, the caret symbol ^ has to be the very last character on the line (no spaces after it) and the next line needs to be indented (at least one space at the front).

Double Double-quotes

When using /command switch, each script command needs to be surrounded by double quotes. As parameters of commands themselves may need to be surrounded by double quotes, those need to be doubled.

For details, see escaping the in-command double-quotes by doubling them.

Percent Sign

If your WinSCP command-line contains percent sign, for example to encode special characters in session URL (particularly in the credentials), it may conflict with special meaning of the percent sign in Windows batch files.

You need to double the percent sign to escape it.

For example in the following batch file, the username user@domain contains the @ sign. As the @ sign has a special meaning in the session URL, it needs to be encoded to %40. But as % sign has a special meaning in the batch file, it needs to be escaped as %%, resulting in final %%40.

winscp.com /log=winscp.log /ini=nul /command ^
    "open sftp://user%%40domain:password@example.com/" ^
    "get *" ^
    "exit"

You can avoid the problem by specifying the credentials using the -username and -password switches:

winscp.com /log=winscp.log /ini=nul /command ^
    "open sftp://example.com/ -username=user@domain -password=password" ^
    "get *" ^
    "exit"

Advertisement

Last modified: by martin