将具有复杂参数的批处理文件命令转换为PowerShell

时间:2017-03-04 20:52:43

标签: powershell syntax winscp

我在.bat中有以下内容(这可行):

"%winscp%" /ini=nul ^
           /log=C:\TEMP\winscplog.txt ^
           /command "open scp://goofy:changeme@10.61.10.225/ -hostkey=""ssh-rsa 2048 d4:1c:1a:4c:c3:60:d5:05:12:02:d2:d8:d6:ae:6c:5d""" ^
           "put ""%outfile%"" /home/public/somedir/somesubdir/%basename%" ^
           "exit"

我试图将其复制到像这样的PowerShell脚本中:

& $winscp "/ini=nul" `
           "/log=C:\TEMP\winscplog.txt" `
           "/command" 'open sftp://goofy:changeme@10.61.10.225/ -hostkey="ssh-rsa 2048 d4:1c:1a:4c:c3:60:d5:05:12:02:d2:d8:d6:ae:6c:5d"' `
           "put `"" + $outfile + "`" /home/public/somedir/somesubdir/" + $basename `
           "exit"

当我运行.bat脚本时,文件将上传。

当我运行.ps1脚本时,我得到Host key does not match configured key ssh-rsa

我怀疑我没有在powershell中正确格式化命令,并且在winscp看到它的时候主机密钥被破坏了。

我检查了日志,显示的所有内容都是来自主机的主机密钥。它没有显示我正在使用的密钥。我确认通过更改我的主机并注意到它没有显示在日志中。我比较了.bat和.ps1之间的日志,差异是ps1终止了上面提到的错误。

winscp是一个sftp实用程序。

4 个答案:

答案 0 :(得分:4)

Martin Prikryl(WinSCP的作者)也提供.Net assembly,如果您想切换到PowerShell,这可能是更好的选择。

使用命令行中的参数更新的文档中的

Example

.gz

答案 1 :(得分:3)

cmd.exe(批处理文件)命令行翻译为PowerShell非常棘手 - 非常棘手,PSv3伪参数中的 引入了--%, the stop-parsing symbol,

其目的是允许您将直接之后的所有内容传递给目标程序, cmd.exe - 样式< em> %...% - 样式环境变量引用 仍然扩展。

注意事项

  • --%必须关注要调用的外部实用程序的名称/路径(它不能首先命令行上的令牌),因此必须使用 PowerShell 定义和引用实用程序可执行文件(路径)本身,如果由[environment]变量传递句法。

  • --%必要性(最多)读取行的末尾 [1] ,所以使用行继续字符在多行中传播命令。不受支持

适用于您的情况,这意味着:

  • %winscp%必须翻译为其PowerShell等效项$env:winscp,后者必须以&,PowerShell的调用运算符为前缀,这在调用外部命令时是必需的由变量或带引号的字符串指定。
  • & $env:winscp必须后跟--%,以确保所有剩余的参数都通过未修改的方式传递(%...%变量引用的扩展除外)。
  • 原始命令的参数列表可以在--%之后按原样粘贴,但必须在一行

因此,在您的情况下最简单的方法 - 虽然以牺牲必须使用单行为代价 - 是:

# Invoke the command line with --%
# All arguments after --% are used as-is from the original command.
& $env:winscp --% /ini=nul /log=C:\TEMP\winscplog.txt /command "open scp://goofy:changeme@10.61.10.225/ -hostkey=""ssh-rsa 2048 d4:1c:1a:4c:c3:60:d5:05:12:02:d2:d8:d6:ae:6c:5d""" "put ""%outfile%"" /home/public/somedir/somesubdir/%basename%" "exit"

[1] --%将所有内容视为传递,直到行尾或下一个未引用的|出现(以及当前保留的将来使用{ {1}}和&&),以先到者为准。停在||允许管道输出 |命令到另一个命令 即使--%,PowerShell自己的行继续符,也被视为传递文字。使用`时,cmd.exe甚至不参与(除非您明确使用--%),因此也不能使用其行继续符cmd --% /c ...。< / SUP>

答案 2 :(得分:2)

每当我必须从PowerShell调用可执行文件时,我总是将参数作为列表传递,如下所示。我也使用单引号,除非我实际上替换变量,在这种情况下我必须使用双引号。

 & SomeUtility.exe @('param1','param2',"with$variable")

当参数中有空格时,它会变得有点棘手,因为您可能必须提供引号,以便实用程序可以正确地解析命令。

您的示例更加棘手,因为WinScp需要用引号括起来的/command参数的参数,以及 double 引号中包含的任何字符串。由于WinScp,所有这些都需要保留。我相信以下内容可行。为了便于阅读,我将参数分解为多行。我还假设您已成功填充了$winscp$outfile$basename个变量。

$params = @(
  '/ini=nul',
  '/log=C:\TEMP\winscplog.txt',
  '/command',
  '"open scp://goofy:changeme@10.61.10.225/ -hostkey=""ssh-rsa 2048 d4:1c:1a:4c:c3:60:d5:05:12:02:d2:d8:d6:ae:6c:5d"""',
  ('"put ""' + $outfile + '"" /home/public/somedir/somesubdir/' + $basename + '"'),
  '"exit"'
)

& $winscp $params

注意第五个参数的括号;这是由于那里的字符串连接操作。 (如果没有括号,每个操作数都会单独添加到列表中 - 您可以通过查看$params.Count来确认。)另请注意,如果您有任何操作数,则需要在日志文件路径周围使用引号把它改成带空格的东西。

答案 3 :(得分:1)

我运行了你的代码(修改后可以使用我自己的服务器),并得到以下日志:

. 2017-03-04 15:32:24.387 Command-line: "C:\Program Files (x86)\WinSCP\WinSCP.exe" /ini=nul /log=C:\TEMP\winscplog.txt /command "open sftp://goofy:***@10.61.10.225/ -hostkey=ssh-rsa" 2048 d4:1c:1a:4c:c3:60:d5:05:12:02:d2:d8:d6:ae:6c:5d"" exit
. 2017-03-04 15:32:24.388 Time zone: Current: GMT-6, Standard: GMT-6 (Central Standard Time), DST: GMT-5 (Central Daylight Time), DST Start: 3/12/2017, DST End: 11/5/2017
. 2017-03-04 15:32:24.388 Login time: Saturday, March 4, 2017 3:32:24 PM
. 2017-03-04 15:32:24.388 --------------------------------------------------------------------------
. 2017-03-04 15:32:24.388 Script: Retrospectively logging previous script records:
> 2017-03-04 15:32:24.388 Script: open sftp://goofy:***@10.61.10.225/ -hostkey=ssh-rsa
. 2017-03-04 15:32:24.388 --------------------------------------------------------------------------

注意第一行中如何在-hostkey=ssh-rsa之后立即插入双引号,在最后一行中,-hostkey参数将从我们预期的内容中截断。

-hostkey参数围绕内部双引号加倍后,我能够成功连接:

"/command" 'open sftp://goofy:changeme@10.61.10.225/ -hostkey=""ssh-rsa 2048 d4:1c:1a:4c:c3:60:d5:05:12:02:d2:d8:d6:ae:6c:5d""' `