如何使用expect从SFTP服务器捕获sftp ls命令的输出?

3

最近三天以来,我一直在苦苦思索如何编写一个bash脚本,以自动从SFTP服务器下载文件。我已经构建了程序的结构,并在代码片段中进行了测试,但是我卡在这里。

我是这样登录到SFTP服务器的:

/usr/bin/expect <<EOD
spawn sftp $ftp_server
expect "password:"
send "$password\r"
expect "sftp>"
send "ls\r"
expect "sftp>\r"
send "exit\r"
EOD

我希望循环遍历ls命令的输出,以决定下载哪个文件。我尝试将输出重定向到文本文件中,然后从那里获取文件名,但它也会存储"sftp>"提示和其他无关信息。如何存储干净的expect ls输出并对其进行循环?


1
如果您在自动化sftp命令行实用程序方面遇到了问题,您应该考虑使用perl、python、c#、java或其他您熟悉的语言编写自己的实用程序。所有这些语言都有可用的ssh/sftp客户端库,您将对sftp协议拥有更多控制权。 - Kenster
2个回答

4
使用-b开关来传递一个带有命令(ls)的脚本,而不是将它们输入标准输入流。
这样sftp就会以批处理模式运行,没有提示符。

1
以下是如何将所有文件名捕获到列表中的示例:
#!/bin/sh
# the next line restarts using expect \
    LC_TYPE=C exec expect -f "$0" -- "$@"

# do not show sftp output by default 
log_user 0

set ftp_server 127.0.0.1
set password pass
set sftp_prompt {sftp> }

spawn -noecho sftp $ftp_server

expect "password:"
send "$password\r"

expect $sftp_prompt

# 'ls -1' will show filenames line by line
send "ls -1\r"

# ignore echo of command from sftp
expect -re {ls -1\r?\n}

# init empty list for filename collecting
set files {}

expect -re {([^\r\n]+)\r?\n} {
    # catch each filename line by line and put it to list 'files'
    lappend files $expect_out(1,string)

    # run current 'expect' again to catch next filename
    exp_continue
} -ex $sftp_prompt {
    # catch sftp prompt to break
}

# loop over example :)
foreach f $files {
    puts $f
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接