31 jan 2006 kl. 01.46 skrev Malcolm Fitzgerald:
On 29/01/2006, at 2:22 AM, Björn Lundin wrote:
I'd do it with Expect, but other people will proberbly use your approach:
if you can 'do shell script' this, from a folderaction,
giving the script it's input parameters, you're basically done
How do we give the script it's input parameters?
Treat it as any command-line program. ie parameters after command name
Usage
autoput.tcl Username Password Ftp_Server Remote_Directory Local_Directory
if run at prompt, and you did chmod a+x autoput.tcl
or
expect -f autoput.tcl Username Password Ftp_Server Remote_Directory Local_Directory
if you did not make it executable with chmod
(I assume it is saved as autoput.tcl)
Ie with Usename and Password, login to Ftp_Server, cd to Remote_directory,
and put all files from my disk, in Local_Directory there.
An option to delete or rename the file is at top. Right now it just prints that it
would delete or rename the local file, if the transmission was successful
I had to run it like this
on adding folder items to this_folder after receiving added_items
try
set shellscript to "/usr/bin/expect -f /Users/bnl/programming/tcl/autoput.tcl me abc della tmp_ftp ~/Desktop/move_to_della"
do shell script shellscript
end try
end adding folder items to
where
me is the user,
abc is the password
della is the server
tmp_ftp is the remote directory, relative to the login directory
and ~/Desktop/move_to_della is the directory
on my desktop where I drop the files
the set shellscript line is on one (1) line
The applescript snippet is saved in
/Library/Scripts/Folder Action Scripts/ftp_upload.scpt
and set it as folderaction for my drop-directory on the desktop.
I saw an error in the sample sent to the newsgroup, so
I fixed (recursive iteration into subfolders)
and then got a bit carried away. Below is tested script.
I order to delete sent files, remove # on line 134
I order to rename sent files, remove # on line 137
To choose beween rename or delete change line 16 (set gDeleteAfterSend 0) to (set gDeleteAfterSend 1)
(Flaw - does not remove recursive Directories)
turn on/off debug info on line 13 (set gDebug 0 or set gDebug 1)
######### script start ######
#!/usr/bin/expect
# exitcodes :
# 0 - Files found and delivered OK
# 1 - No files found to deliver
# 2 - Login failure
# 3 - No such remote directory (cd to it failed)
# 4 - could not PUT file
# 5 - Their lockfile found
# 10 - Timeout in any operation
# Config/globl variables
set gFilelist {}
set gDebug 0
set gMyLockFilename Lock.expect
set gTheirLockFilename Lock.their
set gDeleteAfterSend 0
set gRenameSuffix "sent"
set gSendFilesSuffix "txt"
#-----------------------------------------
proc D {What} {
global gDebug
if {$gDebug} {
puts stderr $What
}
}
#-----------------------------------------
proc Lock {Dir} {
global gMyLockFilename gTheirLockFilename argv0
# 1 - check if their lock exists
# 2 - if not, put our lock there
# 3 - check (1) again, to resolve races
# 4 - if we find their lock file now, yield, by delete our lock, and exit 1
# 5 - If we get here we are done, exit ok
set Some_List {}
# (1)
set Some_List [glob -nocomplain [file join $Dir $gTheirLockFilename]]
if {[llength $Some_List]} {
D "$gTheirLockFilename found, waiting until next poll"
return 0
} else {
# (2)
set FileID [open [file join $Dir $gMyLockFilename] {CREAT WRONLY}]
puts $FileID "[pid]\n$argv0"
close $FileID
}
# (3)
set Some_List {}
set Some_List [glob -nocomplain [file join $Dir $gTheirLockFilename]]
# (4)
if {[llength $Some_List]} {
D "$gTheirLockFilename found, yielding, removing our lock"
catch {[file delete [file join $Dir $gMyLockFilename]]}
return 0
} else {
# (5)
return 1
}
}
#-----------------------------------------
proc Unlock {Dir} {
global gMyLockFilename
catch {[file delete [file join $Dir $gMyLockFilename]]}
}
#-----------------------------------------
#Recursive listing of directories from a point in the filesystem
#Resulting list is to be found in global gFilelist
#Since we just append to the list, the caller should empty it first!
proc Fill_Filelist {Directory} {
global gFilelist gSendFilesSuffix
set Cur_Dir [pwd]
cd $Directory
D "*.$gSendFilesSuffix"
foreach File_Dir [glob -nocomplain *.$gSendFilesSuffix] {
if {[file isdirectory $File_Dir]} {
Fill_Filelist $File_Dir
} elseif {[file isfile $File_Dir]} {
lappend gFilelist [file join [pwd] $File_Dir]
}
}
cd $Cur_Dir
}
#-----------------------------------------
proc Autoput {Username Password Ftp_Server Remote_Directory Local_Directory} {
global timeout, gFilelist gDeleteAfterSend gRenameSuffix
set timeout 5 ; # Timeout for connecting in seconds, changed when PUTting files below.
set gFilelist {}; # Empty before each run
Fill_Filelist $Local_Directory ; # This list holds all FILES in and below Local_Directory
if {![llength $gFilelist]} {
D "No files found to send"
return 1
}
spawn ftp $Ftp_Server
expect {
Name*: {send "$Username\r"}
timeout {return 10 }
}
expect {
*ssword: {send "$Password\r"}
timeout {return 10 }
}
expect {
\n530* {D "Could not log in"
return 2}
\n230* {send "binary\r"}
timeout {return 10 }
}
expect {
\n200* {send "cd $Remote_Directory\r"}
timeout {return 10 }
}
expect {
\n550* {D "Could not cd to $Remote_Directory"
send "bye\r"
return 3}
\n250* {# This is the OK answer, just go on, we're in now}
timeout {return 10 }
}
set timeout 600; # 10 minutes should be long enough to send away a file.
foreach Potential_File $gFilelist {
send "put $Potential_File [file tail $Potential_File]\r"
expect {
\n226* {
if {$gDeleteAfterSend} {
D "Would delete file $Potential_File here, but disabled"
# file delete $Potential_File
} else {
D "rename $Potential_File here, to $Potential_File.$gRenameSuffix , but disabled"
# file rename $Potential_File $Potential_File.$gRenameSuffix
}
}
\n550* {
# D "' $expect_out(buffer) '"
D "Could not PUT $Potential_File"
send "bye\r"
return 4
}
timeout {return 10}
}
}
set timeout 5; # 5 seconds to bring it down in a nice way.
send "bye\r"
expect { eof {}
timeout {return 10}
}
return 0
}
#-----------------------------------------
#Usage
#autoput.tcl Username Password Ftp_Server Remote_Directory Local_Directory
#Begin
set Username [lindex $argv 0]
set Password [lindex $argv 1]
set Ftp_Server [lindex $argv 2]
set Remote_Directory [lindex $argv 3]
set Local_Directory [lindex $argv 4]
# if Lock is successfull, we 'know' that we have a directory
# with OK files, for ourselves...
if {! [Lock $Local_Directory]} {
exit 5
}
set Result [Autoput $Username \
$Password \
$Ftp_Server \
$Remote_Directory \
$Local_Directory ]
Unlock $Local_Directory
# Pass on exitcode to shell
exit $Result
######## script stop