我能够使用scp传输文件并期望,现在我尝试一次上传多个文件:
#!/usr/bin/expect -f
# Escapes spaces in a text
proc esc text {
return [regsub -all {\ } $text {\\&}]
}
# Uploads several files to a specified server
proc my_scp_multi {ACCOUNT SERVER PW files newfolder} {
set timeout 30
send_user -- "\n"
spawn scp $files $ACCOUNT@$SERVER:[esc $newfolder]
match_max 100000
# Look for password prompt
expect {
-re ".*Connection closed.*" {
sendError "\n\n\nUpload failed!\nPlease check the errors above and start over again.\nThis is most likely induced by too many wrong password-attempts and will last quite a time!"
}
-re ".*Permission denied.*" {
sendError "\n\n\nUpload failed!\nPlease check the errors above and start over again.\nYou entered most likely a wrong password!"
}
-re ".*Are.*.*yes.*no.*" {
send "yes\n"
exp_continue
#look for the password prompt
}
-re ".*sword.*" {
# Send password aka $PW
send -- "$PW\r"
# send blank line (\r) to make sure we get back to gui
send -- "\r\n"
exp_continue
}
send_user -- "Upload successful!\n"
}
set timeout -1
}
当我想上传多个文件时,sh命令是:
scp $a $b $c user@server:$folder
,所以我致电my_scp_multi "ACCOUNT" "SERVER" "PW" "~/testfileA ~/testfileB ~/testfileC" "~/test/"
。这也产生了这个输出:
spawn scp ~/testfileA ~/testfileB ~/testfileC user@server:~/test/
user@server's password:
~/testfileA ~/testfileB ~/testfileC: No such file or directory
似乎将“〜/ testfileA~ / testfileB~ / testfileC”视为一个文件。但是,当我将scp ~/testfileA ~/testfileB ~/testfileC user@server:~/test/
复制粘贴到控制台时,它可以正常工作!
我做错了什么?我已经尝试了"\"~/testfileA\" \"~/testfileB\" \"~/testfileC\""
等等,但根本没有任何作用。
有任何想法或建议吗?
EDITS
P.S。:我正在传输相当小的文件。建立连接是转移的最大部分。这就是我希望在一个scp中完成的原因。
P.P.S .: 我玩了一下,想出了:
my_scp_multi3 "user" "server" "pw" "~/a\ b/testfileA, ~/a\\ b/testfileB, ~/a\\\ b/testfileC" "~/test"
使用您的第一个解决方案{*}[split $files ","]
和
my_scp_multi2 "user" "server" "pw" "~/a b/testfileA" "~/a\ b/testfileB" "~/a\\ b/testfileC" "~/test"
使用您的第二个解决方案。这打印:
~/a b/testfileA: No such file or directory
~/a\ b/testfileB: No such file or directory
~/a\ b/testfileC: No such file or directory
和
~/a b/testfileA: No such file or directory
~/a b/testfileB: No such file or directory
~/a\ b/testfileC: No such file or directory
(顺便说一下:我当然移动了文件:))
感谢所有答案,我的解决方案:
使用 \ n \ 0(nullbyte)作为分隔符,因为它是除/和\之外的唯一符号,可能不会在文件名中使用。
#!/usr/bin/expect -f
# Escapes spaces in a text
proc esc text {
return [regsub -all {\ } $text {\\&}]
}
# Returns the absolute Filepath
proc makeAbsolute {pathname} {
file join [pwd] $pathname
}
proc addUploadFile {files f} {
if {$files != ""} {
set files "$files\0"
}
return "$files[makeAbsolute $f]"
}
#Counts all files from an upload-list
proc countUploadFiles {s} {
set rc [llength [split $s "\0"]]
incr rc -1
return $rc
}
# Uploads several files from a list (created by addUploadFile) to a specified server
proc my_scp_multi {ACCOUNT SERVER PW files newfolder} {
foreground blue
set nFiles [countUploadFiles $files]
set timeout [expr $nFiles * 60]
send_user -- "\n"
spawn scp -r {*}[split $files "\0"] $ACCOUNT@$SERVER:[esc $newfolder]
match_max 100000
# Look for password prompt
expect {
-re ".*Connection closed.*" {
sendError "\n\n\nUpload failed!\nPlease check the errors above and start over again.\nThis is most likely induced by too many wrong password-attempts and will last quite a time!"
}
-re ".*Permission denied.*" {
sendError "\n\n\nUpload failed!\nPlease check the errors above and start over again.\nYou entered most likely a wrong password!"
}
-re ".*Are.*.*yes.*no.*" {
send "yes\n"
exp_continue
#look for the password prompt
}
-re ".*sword.*" {
# Send password aka $PW
send -- "$PW\r"
# send blank line (\r) to make sure we get back to gui
send -- "\r\n"
exp_continue
}
send_user -- "Upload successful!\n"
}
set timeout -1
}
set fls [addUploadFile "" "a b/testfileA"]
set fls [addUploadFile $fls "a b/testfileB"]
set fls [addUploadFile $fls "a b/testfileC"]
my_scp_multi "user" "server" "pw" $fls "~/test"
答案 0 :(得分:2)
您不希望将文件名作为单个字符串发送。要么这样做:
spawn scp {*}[split $files] $ACCOUNT@$SERVER:[esc $newfolder]
继续引用文件名:
my_scp_multi "ACCOUNT" "SERVER" "PW" "~/testfileA ~/testfileB ~/testfileC" "~/test/"
或执行此操作:
proc my_scp_multi {ACCOUNT SERVER PW args} {
set timeout 30
send_user -- "\n"
set files [lrange $args 0 end-1]
set newfolder [lindex $args end]
spawn scp {*}$files $ACCOUNT@$SERVER:[esc $newfolder]
然后不引用文件名
my_scp_multi "ACCOUNT" "SERVER" "PW" ~/testfileA ~/testfileB ~/testfileC "~/test/"
splat({*}
)将列表拆分为单个元素,因此spawn命令可以看到多个单词,而不是单个单词。见http://tcl.tk/man/tcl8.5/TclCmd/Tcl.htm
答案 1 :(得分:1)
您可以生成一个shell,然后运行scp命令:
spawn bash
send "scp $files $ACCOUNT@$SERVER:[esc $newfolder]\r"
这允许全局扩展但增加了额外的内务管理,因为在scp进程完成时你需要陷阱,因为你仍然有一个shell运行。 您可以在下面添加到您的预期块:
-re "100%" {
if { $index < $count } {
set index [expr $index + 1]
exp_continue
}
}
其中index是要传输的文件的数量,并计算nr个文件。
答案 2 :(得分:0)
您应该使用SSH公钥身份验证,而不是使用expect
键入密码。正确设置后,scp
无需人工输入密码即可正常工作,同时保持系统安全。 expect
将为您免除所有麻烦。
如果有一些原因导致您无法使用pubkey,您可能会发现当sftp
非常有用,因为它接受批处理命令文件为-b batchfile
。请参阅man 1 sftp
expect
实际拆分参数时,这不是一个很好的解决方案