Я смог передавать файлы с помощью 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\""
и подобные вещи, но вообще ничего не работало.
Есть идеи или предложения?
РЕДАКТИРОВАТЬ
P.S .: Передаю файлы небольшого размера. Установление соединения - самая большая часть перевода. Это причина, по которой я хочу, чтобы это было сделано в ОДНОМ scp.
П.П.С .: Я немного поигрался и придумал:
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 (нулевой байт) в качестве разделителя, потому что это единственный символ, кроме / и \, который не может использоваться в именах файлов.
#!/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
- единственные запрещенные символы в имени файла. Новая строка - это допустимый символ имени файла. Попробуйте в bash:touch $'a\nfile\nname'
. Именно этот факт вызывает массу головных болей у разработчиков сценариев оболочки и разработчиков инструментов: именно поэтому в GNU find есть директива-print0
, а в xargs --0
и т. Д. И т. Д. - person glenn jackman   schedule 28.01.2014foreach f {"a b/A" "a b/B" "a b/C"} {lappend fls [makeAbsolute $f]}; ... spawn ... {*}$files ...
- person glenn jackman   schedule 28.01.2014send
lpr-Command, напримерlpr a b.pdf
,lpr a\ b.pdf
,lpr a\\ b.pdf
илиlpr a\\\ b.pdf
, ничего работать не будет. Опять же, когда я вставлю код в консоль, он заработает? Разве tcl не отправляет команду в виде текста? - person 3244611user   schedule 29.01.2014lpr 'a b.pdf'
. Но я до сих пор не понимаю, почему команда не работает, когда работает скопированная. - person 3244611user   schedule 29.01.2014