如何通过expect脚本连接sftp后提取纯文件名目录列表
问题原因
两个核心问题导致输出不符合预期:
- sftp默认
ls命令会根据终端宽度自动适配为多列排布,不会逐行展示文件名 - expect默认会回显全量交互过程内容,包含spawn启动提示、连接信息、sftp交互提示符、末尾系统邮件提示等冗余内容
调整方案
修改expect脚本,从关闭冗余回显、强制ls单列输出、定向提取目标文件名三个维度调整,修改后完整脚本如下:
set timeout 10000 # 关闭默认交互回显,屏蔽无关过程输出 log_user 0 spawn sftp -o ConnectTimeout=3 user@192.1.6.6 expect "*?assword*" send "tech\r" expect "sftp>" send "cd /global/scripts/log\r" expect "sftp>" # 给ls加-1参数(数字1),强制单列逐行输出文件名 send "ls -1 20220703*\r" # 正则捕获ls返回的文件列表内容 expect -re "ls -1 20220703\*\r\n(.*?)\r\nsftp>" { set file_lines [split $expect_out(1,string) "\r\n"] foreach line $file_lines { set line [string trim $line] # 仅输出非空、匹配目标前缀的文件名 if {$line ne "" && [string match "20220703*" $line]} { puts $line } } } send "bye\r" expect eof
关键修改点说明
- 新增
log_user 0配置:关闭expect默认的全量交互打印,从源头屏蔽spawn提示、密码行、sftp>提示符、连接成功通知、系统邮件提示等所有无关内容 - ls命令新增
-1参数:强制sftp的ls结果为单列模式,每个文件名单独占一行,解决原多列排布问题 - 新增定向捕获逻辑:通过正则匹配只提取ls命令返回的文件列表段,逐行校验过滤后仅输出符合20220703前缀的有效文件名,避免残留杂项
- 末尾新增
expect eof:等待sftp进程正常退出,避免僵尸进程残留
执行命令保持不变,仍为:
expect expect.dat
执行后即可得到逐行排列的纯目标文件名输出,和预期结果完全一致。
内容的提问来源于stack exchange,提问作者Jeniffer Lorena Guillen Castro
相关产品推荐
相关产品推荐

