在Shell脚本中使用Expect命令获取文件列表

问题描述

如何在shell脚本中使用Expect命令获取文件列表

我的脚本外壳:

remotepass="12345"

echo
echo "list files ssh"
echo "=========="
listDoc=$(ssh user@111.111.111.111 ls /data/dcrm_int/ftp/out/rpt/dwh/20200820/*DWH_CRM_SYS_OPERLOG_20200820*)
echo $listDoc

echo
echo "list files"
echo "=========="
for document in $listDoc; do
    echo $document
done

cat > expect_1.dat << EOF
    spawn ssh user@111.111.111.111 ls /data/dcrm_int/ftp/out/rpt/dwh/20200820/*DWH_CRM_SYS_OPERLOG_20200820*
    expect "*?assword*"
    send "$remotepass\r"
    interact
EOF
listDoc=$(expect "expect_1.dat")

echo
echo "result"
echo "======"
echo $listDoc

echo
echo "list files"
echo "=========="
for document in $listDoc; do
    echo $document
done

result

我希望得到的结果就像第一个红色方框

有没有办法只显示文件和目录

解决方法

默认情况下,spawn回显所有已发送的内容和已接收的内容。 您可以通过将其添加到期望的脚本开始中来禁用它:

log_user 0

这将删除不需要的起始文本。

一个看不见的问题是输出在每行末尾包含回车符 control-M 。您可以这样做

echo "$listDoc"|cat -v

每行将以^M结尾。这是因为spawn使用的pty将继承当前的stty设置,其中包括onlcr,即将输出换行换成回车换行。您可以通过几种方式删除这些字符,但也可以通过将其添加到期望脚本开始中来避免它们:

set stty_init -onlcr

另一个问题是输出以空行开头。您可以通过添加

来避免这种情况
expect "\n"

就在interact之前。

确保在外壳程序中双引号:

echo "$listDoc"
,

请接受@meuh's answer

一个外壳技巧,使用,将输出的读入数组:

mapfile -t listDoc < <(expect "expect_1.dat")

然后

echo
echo "list files"
echo "=========="
for document in "${listDoc[@]}"; do
    echo "$document"
done

阅读Security implications of forgetting to quote a variable in bash/POSIX shells


列出meuh的建议:

cat > expect_1.dat << EOF
    log_user 0
    set stty_init -onlcr
    spawn ssh user@111.111.111.111 ls /data/dcrm_int/ftp/out/rpt/dwh/20200820/*DWH_CRM_SYS_OPERLOG_20200820*
    expect "*?assword*"
    send "$remotepass\r"
    log_user 1
    expect eof
EOF

引号heredoc通常是一个好主意,特别是如果您将在Expect中使用更多代码并使用Expect变量的话。然后,您可以通过环境传递外壳变量以期望:

export remotepass
# note the quotes in the next line: the whole heredoc is a single quoted string
cat > expect_1.dat << 'EOF'
    log_user 0
    set stty_init -onlcr
    spawn ssh user@111.111.111.111 ls /data/dcrm_int/ftp/out/rpt/dwh/20200820/*DWH_CRM_SYS_OPERLOG_20200820*
    expect "*?assword*"
    send "$env(remotepass)\r"   # using the environment variable
    log_user 1
    expect eof
EOF