[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Net::FTP questions...

Lincoln Anderson

9/11/2006 10:39:00 PM

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Hello...

I am attempting to write a client side script that mirrors a user's
/home/* on a remote server. Granted, I *could* use ftpmirror in my
Ubuntu distribution, but I'd like to get more familiar with network
and filesystem operations in Ruby.

The basic algorithm as I see it would be to logon, get a list of all
files and folders via the Net::FTP.list(*args) command, run it through
a block or a for loop or some other iterator, ducking into
subdirectories as needed (and mkdir-ing them on the client side), and
doing a get() of all the files in each subdirectory.

Here's where my problem comes in. How can I tell from the list array
whether an item is a directory or a file to be copied? Is there
something I can use (such as an FTP command) to catch a clue on how to
implement this? I know this is possible, as ftpmirror is done with
PERL and Ruby can do anything PERL can do - better :)

Google is no help, and neither is running searches on ruby-talk
itself... Anyone done anything similar and have any tips? Any advice
whatsoever is appreciated.

Lincoln Anderson
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail....

iD8DBQFFBeV4Kte2c0P8BH0RAo4TAJ9sdFbwO/W6JdMpIxNULjC0ivjGdACbBSr5
Qqg1SW+aKBPyWB4rURKu5Lk=
=2OL8
-----END PGP SIGNATURE-----


5 Answers

Vincent Arnoux

9/12/2006 8:45:00 AM

0

Hi,

Le mardi 12 septembre 2006 à 07:39 +0900, Lincoln Anderson a écrit :
> Here's where my problem comes in. How can I tell from the list array
> whether an item is a directory or a file to be copied? Is there
> something I can use (such as an FTP command) to catch a clue on how to
> implement this? I know this is possible, as ftpmirror is done with
> PERL and Ruby can do anything PERL can do - better :)

The output of FTP#ls should be something like :
drwxr-x--- 2 login ftp 96 Sep 11 16:07 mydir
-rwxr-x--- 2 login ftp 96 Sep 11 16:07 myfile

So you will know an entry is a directory if the string begins by "d".

Vincent




Lincoln Anderson

9/12/2006 2:51:00 PM

0

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Vincent Arnoux wrote:
> Hi,
>
> Le mardi 12 septembre 2006 à 07:39 +0900, Lincoln Anderson a écrit
> :
>> Here's where my problem comes in. How can I tell from the list
>> array whether an item is a directory or a file to be copied? Is
>> there something I can use (such as an FTP command) to catch a
>> clue on how to implement this? I know this is possible, as
>> ftpmirror is done with PERL and Ruby can do anything PERL can do
>> - better :)
>
> The output of FTP#ls should be something like : drwxr-x--- 2
> login ftp 96 Sep 11 16:07 mydir -rwxr-x--- 2 login ftp
> 96 Sep 11 16:07 myfile
>
> So you will know an entry is a directory if the string begins by
> "d".
>
> Vincent
>
>
>
>
>

Yeah, I noticed that after my post... I guess I was trying to
complicate things :)

Thanks,
Lincoln Anderson
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail....

iD8DBQFFBsk+Kte2c0P8BH0RAgagAJ99pzUNbgqd4Xla9/NYxXfCqt7ZJgCfc0qd
oC7upPw6SIZTOEMr17A66FE=
=hrJu
-----END PGP SIGNATURE-----


Jamey Cribbs

9/12/2006 3:14:00 PM

0

Lincoln Anderson wrote:
> Here's where my problem comes in. How can I tell from the list array
> whether an item is a directory or a file to be copied? Is there
> something I can use (such as an FTP command) to catch a clue on how to
> implement this? I know this is possible, as ftpmirror is done with
> PERL and Ruby can do anything PERL can do - better :)
>
Here's a class I defined to use in a script I run that moves files
between various Unix and Windows servers at my company. Haven't looked
at the code in a while, so it might be ugly, but it works!


class FTPLocation
def initialize(host, userid, password, path)
@host, @userid, @password = host, userid, password

if path.nil?
@path = './'
else
@path = path
end
end


#-----------------------------------------------------------------------
# to_s

#-----------------------------------------------------------------------
def to_s
return '%s - %s' % [@host, @path]
end


#-----------------------------------------------------------------------
# connect

#-----------------------------------------------------------------------
def connect
@ftp = Net::FTP.new(@host, @userid, @password)
# @ftp.debug_mode = true
@ftp.chdir(@path)
end


#-----------------------------------------------------------------------
# empty?

#-----------------------------------------------------------------------
def empty?
@ftp.list.each do |entry|
next if entry[0] == 'd'
return false
end
return true
end


#-----------------------------------------------------------------------
# each_file

#-----------------------------------------------------------------------
def each_file
t = Time.now
@ftp.list.each do |entry|
next if entry[0] == 'd'
filename = entry.split(' ')[-1]
next if t - @ftp.mtime(filename) < 300
yield filename
end
end


#-----------------------------------------------------------------------
# file_exists?

#-----------------------------------------------------------------------
def file_exists?(filename)
@ftp.list.each do |entry|
next if entry[0] == 'd'
return true if filename == entry.split(' ')[-1]
end
return false
end



#-----------------------------------------------------------------------
# get_file

#-----------------------------------------------------------------------
def get_file(filename, dest_path, xfer_type)
if xfer_type == 'binary'
@ftp.getbinaryfile(filename, dest_path)
else
@ftp.gettextfile(filename, dest_path)
end
end


#-----------------------------------------------------------------------
# put_file

#-----------------------------------------------------------------------
def put_file(source_path, filename, xfer_type)
if xfer_type == 'binary'
@ftp.putbinaryfile(source_path, filename)
else
@ftp.puttextfile(source_path, filename)
end
end


#-----------------------------------------------------------------------
# delete_file

#-----------------------------------------------------------------------
def delete_file(filename)
@ftp.delete(filename)
end


#-----------------------------------------------------------------------
# close

#-----------------------------------------------------------------------
def close
@ftp.close if @ftp
end
end


Confidentiality Notice: This email message, including any attachments, is for the sole use of the intended recipient(s) and may contain confidential and/or privileged information. If you are not the intended recipient(s), you are hereby notified that any dissemination, unauthorized review, use, disclosure or distribution of this email and any materials contained in any attachments is prohibited. If you receive this message in error, or are not the intended recipient(s), please immediately notify the sender by email and destroy all copies of the original message, including attachments.

Vincent Arnoux

9/12/2006 4:48:00 PM

0


Le mercredi 13 septembre 2006 à 00:14 +0900, James Cribbs a écrit :
Lincoln Anderson wrote:
> Here's where my problem comes in. How can I tell from the list array
> whether an item is a directory or a file to be copied? Is there
> something I can use (such as an FTP command) to catch a clue on how to
> implement this? I know this is possible, as ftpmirror is done with
> PERL and Ruby can do anything PERL can do - better :)

Perhaps this can be useful to browse the FTP server tree (directory
names finish by '/', others are files):

def recursive_listing(ftp, path)
liste_ftp = Array.new
list = ftp.ls(path)
if list.length == 0
return []
end
if list[0].split[0] == 'total'
list.delete_at(0)
end
if list[0].split[8] == '.'
list.delete_at(0)
end
if list[0].split[8] == '..'
list.delete_at(0)
end
list.each { |str|
if str.split[0].index('d') == 0
liste_ftp += [path + "/" + str.split[8] + "/"]
liste_ftp += [recursive_listing(ftp, path + "/"
+ str.split[8])]
else
liste_ftp += [path + "/" + str.split[8]]
end
}
return liste_ftp.flatten
end

ftp = Net::FTP.new('ftp_serveur')
ftp.login('login', 'passwd')
ftp_list = recursive_listing(ftp, 'starting_directory')
ftp.close


It might need some corrections depending your FTP server configuration.

Cheers,
Vincent




Lincoln Anderson

9/12/2006 5:26:00 PM

0

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Vincent Arnoux wrote:
> Le mercredi 13 septembre 2006 à 00:14 +0900, James Cribbs a écrit :
> Lincoln Anderson wrote:
>> Here's where my problem comes in. How can I tell from the list
>> array whether an item is a directory or a file to be copied? Is
>> there something I can use (such as an FTP command) to catch a
>> clue on how to implement this? I know this is possible, as
>> ftpmirror is done with PERL and Ruby can do anything PERL can do
>> - better :)
>
> Perhaps this can be useful to browse the FTP server tree (directory
> names finish by '/', others are files):
>
> def recursive_listing(ftp, path) liste_ftp = Array.new list =
> ftp.ls(path) if list.length == 0 return [] end if list[0].split[0]
> == 'total' list.delete_at(0) end if list[0].split[8] == '.'
> list.delete_at(0) end if list[0].split[8] == '..' list.delete_at(0)
> end list.each { |str| if str.split[0].index('d') == 0 liste_ftp +=
> [path + "/" + str.split[8] + "/"] liste_ftp +=
> [recursive_listing(ftp, path + "/" + str.split[8])] else liste_ftp
> += [path + "/" + str.split[8]] end } return liste_ftp.flatten end
>
> ftp = Net::FTP.new('ftp_serveur') ftp.login('login', 'passwd')
> ftp_list = recursive_listing(ftp, 'starting_directory') ftp.close
>
>
> It might need some corrections depending your FTP server
> configuration.
>
> Cheers, Vincent
>
>
>
>
>
That looks exactly like what I'm trying to do for the directory
hierarchy mirror. I'm still learning to think in Ruby... I keep going
back to C/C++ solutions and other heavy hitter languages... I'll tweak
that and see if I can get it working. I'll post my results when I get
it running (or I have any other insurmountable problems...).

Thanks,
Lincoln Anderson
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail....

iD8DBQFFBu1+Kte2c0P8BH0RAgj9AJ93sCYtnfq8FKx6MmlgGqEYm46RTQCeOi6L
mkZjNSXuR+vpn1JrgPZORaQ=
=CfgK
-----END PGP SIGNATURE-----