Python FTP obtient le fichier le plus récent par date
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.
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()