2

I know how to set to download a file like this, but most files aren't named file-LATEST. How would I be able to download the latest file?

via:

  • date modified
  • timestamp
  • if version.current < version.new then download

Here's what I have so far:

#!/usr/bin/env python

import ftplib
import os
import socket

HOST = 'ftp.site.org'
DIRN = 'dir/'
FILE = 'filename-LATEST.tar.gz'

def main():
    try:
    f = ftplib.FTP(HOST)
except (socket.error, socket.gaierror), e:
    print 'ERROR: cannot reach "%s"' % HOST
    return
print '*** Connected to host "%s"' % HOST

try:
    f.login()
except ftplib.error_perm:
    print 'ERROR:: cannot login anonymously'
    f.quit()
    return
print '*** Logged in as "anonymous"'

try:
    f.cwd(DIRN)
except ftplib.error_perm:
    print 'ERROR: cannot CD to "%s"' % DIRN
    f.quit()
    return
print '*** Changed to "%s" folder' % DIRN

try:
    f.retrbinary('RETR %s' % FILE, open(FILE, 'wb').write)
except ftplib.error_perm:
    print 'ERROR: cannot read file "%s"' % FILE
    os.unlink(FILE)
else:
    print '*** Downloaded "%s" to CWD' % FILE
f.quit()
return

if __name__ == '__main__':
main()
Adam Wenger
  • 17,100
  • 6
  • 52
  • 63
astralkid
  • 21
  • 3
  • 1
    Possible duplicate of [python ftp get the most recent file by date](https://stackoverflow.com/questions/8990598/python-ftp-get-the-most-recent-file-by-date) – Cees Timmerman Aug 08 '17 at 08:24

2 Answers2

0

you have to do ftp.retrlines('LIST',callback) as in the doc of ftplib and parse the result

hoju
  • 28,392
  • 37
  • 134
  • 178
Xavier Combelle
  • 10,968
  • 5
  • 28
  • 52
-1

My answer is not related to ftplib. Its the pexpect way. See the code below

#!/usr/bin/python -B

#Program to download latest file from a FTP directory specified

import sys
import os
import pexpect

if len(sys.argv)!=5:
    print "Usage:"
    print "\t",sys.argv[0],"<IP Address> <Username> <Password> <Directory-Path>"
    print "\t","Use \"\" if there is no password"
    sys.exit(1)

ip=str(sys.argv[1])
usr=str(sys.argv[2])
pswd=str(sys.argv[3])
path=str(sys.argv[4])
timeout=10
log_file=file("temp",'w')

try:
    try:
        child=pexpect.spawn("ftp "+ip)
    except:
        print "failed to connect "+sys.exc_function()
        sys.exit(1)

    x=child.expect(['Name',pexpect.EOF,pexpect.TIMEOUT],timeout)
    if x!=0:
        print "No \"Name\" prompt"
        sys.exit(1)

    child.sendline(usr)
    x=child.expect(["[pP]assword","[lL]ogin [sS]ucess","logged in",
            pexpect.EOF,pexpect.TIMEOUT],timeout)
    if x==0:
        child.sendline(pswd)   #Add case for no password
        y=child.expect(["[lL]ogin [sS]uccess","User "+usr+" logged in", 
        "[iI]correct [lLogin]",pexpect.EOF,pexpect.TIMEOUT],timeout) 
        if y!=0 and y!=1:
            print "Login Failed"
            sys.exit(1)
    elif x!=1 and x!=2:
        print "Authentication Timed Out!!"
        sys.exit(1) 

    child.sendline("cd "+path)
    x=child.expect(["[dD]irectory successfully changed","CWD command successful",
            pexpect.EOF,pexpect.TIMEOUT],timeout) 
    if x!=0 and x!=1:
        print "cd Failed!!!"
        sys.exit(1)

    child.logfile=log_file

    child.sendline("ls -lrt")
    x=child.expect(["[dD]irectory send OK","[tT]ransfer [cC]omplete",
            pexpect.EOF,pexpect.TIMEOUT],timeout)
    if x!=0 and x!=1:
        print "listing failed" 
        sys.exit(1)

    os.system("cat temp | grep '^-' |"+\
         "sed -n '$p' | awk '{print $NF}' > file_name") 

    fd=open("file_name","r")   #for loop is not needed here since there'll be only one line
    for line in fd:
        if line:
             latest_file=line.strip()
             break
        else:
             print "No file found"
             sys.exit(1)
    fd.close()
    child.logfile=sys.stdout
    os.system("rm temp file_name")

    child.sendline("bi")
    child.expect("ftp>")
    child.sendline("ha")
    child.expect("ftp>")

    child.sendline("get "+latest_file)
    x=child.expect(["[tT]ransfer [cC]omplete",
            pexpect.EOF,pexpect.TIMEOUT],200) #Add more error cases here
    if x!=0:
        print "Copy Failed" 
        sys.exit(1)

    child.close()
    sys.exit(0)
except KeyboardInterrupt:
    print "",

ftp prompts will be different for different ftp servers. Try manually once and expect the same in the code. You can add more error cases as well. I used log_file as I cannot pipe the output of ls -lrt within ftp to extract the file name directly.

I know my code is not efficient one.Please edit wherever necessary. However this will work!! Cheers

Ramana Reddy
  • 369
  • 1
  • 8
  • 28