Reputation: 85
I have an array in my bash script:
my_file=("a.txt" "b.txt" "c.txt" "d.txt" "e.txt")
Now in the same file I want to use Expect and make a looping to get some files in sftp. This is my code
/usr/bin/expect <<EOF
set timeout -1
array set param ${!my_file[@]}
spawn sftp $sftp_option $user@$host
expect "Password:"
send "$pswd\r"
expect "sftp>"
for arg in $param; do
send "mget $arg*\r"
expect "sftp>"
done
send "bye\r"
EOF
With that code I can't make a loop with that array above. And I got error like this:
wrong # args: should be "array set arrayName list" while executing "array set param 0 1"
Full Code:
#!/bin/bash
export PATH=$PATH:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin;
homeDir=/home/jlo_apps/daemon/jlo_ex/collection/wssh;
filePID=$homeDir/rsync_rfs_bbni.pid;
trap "rm $filePID; exit" SIGHUP SIGINT SIGTERM;
if [ -e $filePID ]; then
datenow=`date`;
echo "[ Rsync ] There are rsync processes still running...";
echo "========================= $datenow =========================";
exit 1;
else
echo $$ > $filePID;
fi
. $homeDir/get_rfs_bni.conf;
strconn="$dbuser/$dbpass@$dbhost:$dbport/$dbsid";
profile=`$sqlldr_path -s $strconn <<< "select host|| '|' ||username|| '|' ||password|| '|' ||port|| '|' ||outdir from p_epdp where bank='BBNI';" | tail -2 | head -1`;
mapfile mid < <($sqlldr_path -s $strconn <<< "select distinct(substr(mid, 0, 13)) from p_mid where kode_bank = 'BBNI';" | tail -3 | head -2);
host=$(echo $profile | cut -d"|" -f1);
user=$(echo $profile | cut -d"|" -f2);
pswd=$(echo $profile | cut -d"|" -f3);
port=$(echo $profile | cut -d"|" -f4);
outdir=$(echo $profile | cut -d"|" -f5);
/usr/bin/expect <<EOF
set timeout -1
spawn sftp $sftp_option $user@$host
expect "Password:"
send "$pswd\r"
expect "sftp>"
send "cd $outdir\r"
expect "sftp>"
send "lcd $rfshome\r"
expect "sftp>"
foreach arg {${mid[@]}} {
send "mget $arg*\r"
expect "sftp>"
}
send "bye\r"
EOF
rm $filePID;
sleep 10;
datenow=`date`;
echo "========================= $datenow =========================";
Is there any solution for this problem without separate file between bash and Expect?
Upvotes: 1
Views: 3675
Reputation: 246807
It's a bit awkward looking, but you can do this:
$ my_file=("a.txt" "b.txt" "c.txt" "d.txt" "e.txt")
$ expect -f - -- "${my_file[@]}" <<'END'
foreach arg $argv {puts $arg}
END
a.txt
b.txt
c.txt
d.txt
e.txt
The -f -
tells expect to use stdin for the script file.
Then --
ends the command line options, and the remaining arguments go into the argv
list.
Don't forget to use a quoted heredoc, like I demonstrate. Otherwise the shell will expand the expect variables.
Upvotes: 1
Reputation: 189387
The correct syntax to interpolate the array's values would be
array set param ${my_file[@]}
without a !
, but this produces
array set param a.txt b.txt c.txt d.txt e.txt
However, the Expect syntax for creating an array looks like
array set param {one one.txt two two.txt}
with alternating keys and values (more like an associative array than just a list of values). But then you still can't use a shell for
loop inside the Expect script; the language uses a completely different syntax (Expect is based on TCL, not shell script).
Probably you are looking for something like
/usr/bin/expect <<EOF
set timeout -1
spawn sftp $sftp_option $user@$host
expect "Password:"
send "$pswd\r"
expect "sftp>"
foreach arg {${my_file[@]}} {
send "mget $arg*\r"
expect "sftp>"
}
send "bye\r"
EOF
where I cribbed the proper TCL loop syntax from Pass bash array to expect script
Upvotes: 2