Question

J'utilise ftplib pour me connecter à un site FTP.Je souhaite obtenir le fichier le plus récemment téléchargé et le télécharger.Je peux me connecter au serveur FTP et lister les fichiers, je les ai également mis dans une liste et j'ai obtenu le datefield converti.Existe-t-il une fonction/un module capable d'obtenir la date récente et d'afficher la ligne entière de la liste ?

#!/usr/bin/env python

import ftplib
import os
import socket
import sys


HOST = 'test'


def main():
    try:
        f = ftplib.FTP(HOST)
    except (socket.error, socket.gaierror), e:
        print 'cannot reach to %s' % HOST
        return
    print "Connect to ftp server"

    try:
        f.login('anonymous','al@ge.com')
    except ftplib.error_perm:
        print 'cannot login anonymously'
        f.quit()
        return
    print "logged on to the ftp server"

    data = []
    f.dir(data.append)
    for line in data:
        datestr = ' '.join(line.split()[0:2])
        orig-date = time.strptime(datestr, '%d-%m-%y %H:%M%p')


    f.quit()
    return


if __name__ == '__main__':
    main()

RÉSOLU:

data = []
f.dir(data.append)
datelist = []
filelist = []
for line in data:
    col = line.split()
    datestr = ' '.join(line.split()[0:2])
    date = time.strptime(datestr, '%m-%d-%y %H:%M%p')
    datelist.append(date)
    filelist.append(col[3])

combo = zip(datelist,filelist)
who = dict(combo)

for key in sorted(who.iterkeys(), reverse=True):
   print "%s: %s" % (key,who[key])
   filename = who[key]
   print "file to download is %s" % filename
   try:
       f.retrbinary('RETR %s' % filename, open(filename, 'wb').write)
   except ftplib.err_perm:
       print "Error: cannot read file %s" % filename
       os.unlink(filename)
   else:
       print "***Downloaded*** %s " % filename
   return

f.quit()
return

Un problème, est-il possible de récupérer le premier élément du dictionnaire ?ce que j'ai fait ici, c'est que la boucle for ne s'exécute qu'une seule fois et se termine, me donnant ainsi la première valeur triée, ce qui est bien, mais je ne pense pas que ce soit une bonne pratique de le faire de cette façon.

Était-ce utile?

La solution

Si vous avez toutes les dates time.struct_time (strptime vous donnera ceci) dans une liste alors tout ce que vous avez à faire est sort la liste.

Voici un exemple :

#!/usr/bin/python

import time

dates = [
    "Jan 16 18:35 2012",
    "Aug 16 21:14 2012",
    "Dec 05 22:27 2012",
    "Jan 22 19:42 2012",
    "Jan 24 00:49 2012",
    "Dec 15 22:41 2012",
    "Dec 13 01:41 2012",
    "Dec 24 01:23 2012",
    "Jan 21 00:35 2012",
    "Jan 16 18:35 2012",
]

def main():
    datelist = []
    for date in dates:
        date = time.strptime(date, '%b %d %H:%M %Y')
        datelist.append(date)

    print datelist
    datelist.sort()
    print datelist

if __name__ == '__main__':
    main()

Autres conseils

Pour ceux qui recherchent une solution complète pour trouver le dernier fichier dans un dossier :

MLSD

Si votre serveur FTP prend en charge MLSD commande, une solution est simple :

entries = list(ftp.mlsd())
entries.sort(key = lambda entry: entry[1]['modify'], reverse = True)
latest_name = entries[0][0]
print(latest_name)

LISTE

Si vous devez compter sur des produits obsolètes LIST commande, vous devez analyser une liste propriétaire qu’elle renvoie.

La liste commune * nix ressemble à :

-rw-r--r-- 1 user group           4467 Mar 27  2018 file1.zip
-rw-r--r-- 1 user group         124529 Jun 18 15:31 file2.zip

Avec un listing comme celui-ci, ce code fera :

from dateutil import parser

# ...

lines = []
ftp.dir("", lines.append)

latest_time = None
latest_name = None

for line in lines:
    tokens = line.split(maxsplit = 9)
    time_str = tokens[5] + " " + tokens[6] + " " + tokens[7]
    time = parser.parse(time_str)
    if (latest_time is None) or (time > latest_time):
        latest_name = tokens[8]
        latest_time = time

print(latest_name)

Il s’agit d’une approche plutôt fragile.


MDTM

Une solution plus fiable, mais bien moins efficace, consiste à utiliser MDTM commande pour récupérer les horodatages de fichiers/dossiers individuels :

names = ftp.nlst()

latest_time = None
latest_name = None

for name in names:
    time = ftp.voidcmd("MDTM " + name)
    if (latest_time is None) or (time > latest_time):
        latest_name = name
        latest_time = time

print(latest_name)

Commutateur -t non standard

Certains serveurs FTP prennent en charge un protocole propriétaire non standard -t passer pour NLST (ou LIST) commande.

lines = ftp.nlst("-t")

latest_name = lines[-1]

Voir Comment trier les fichiers du dossier FTP par heure de modification.


Téléchargement du fichier trouvé

Quelle que soit l'approche que vous utilisez, une fois que vous avez latest_name, vous le téléchargez comme n'importe quel autre fichier :

file = open(latest_name, 'wb')
ftp.retrbinary('RETR '+ latest_name, file.write)

Voir également

Pourquoi n'utilisez-vous pas l'option next dir ?

ftp.dir('-t',data.append)

Avec cette option, la liste des fichiers est classée dans le temps, du plus récent au plus ancien.Il suffit ensuite de récupérer le premier fichier de la liste pour le télécharger.

Je ne sais pas comment c'est votre FTP, mais votre exemple ne fonctionnait pas pour moi.J'ai modifié quelques lignes liées à la partie tri des dates :

    import sys
    from ftplib import FTP
    import os
    import socket
    import time

    # Connects to the ftp
    ftp = FTP(ftpHost)
    ftp.login(yourUserName,yourPassword)
    data = []
    datelist = []
    filelist = []
    ftp.dir(data.append)
    for line in data:
      col = line.split()
      datestr = ' '.join(line.split()[5:8])
      date = time.strptime(datestr, '%b %d %H:%M')
      datelist.append(date)
      filelist.append(col[8])
    combo = zip(datelist,filelist)
    who = dict(combo)
    for key in sorted(who.iterkeys(), reverse=True):
      print "%s: %s" % (key,who[key])
      filename = who[key]
      print "file to download is %s" % filename
      try:
        ftp.retrbinary('RETR %s' % filename, open(filename, 'wb').write)
      except ftplib.err_perm:
        print "Error: cannot read file %s" % filename
        os.unlink(filename)
      else:
        print "***Downloaded*** %s " % filename
    ftp.quit()
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top