¿Cómo eliminar archivos con un script Python desde un servidor FTP que tienen más de 7 días?

Me gustaría escribir un script de Python que me permita eliminar archivos de un servidor FTP después de que hayan alcanzado una cierta edad. Preparé el documento siguiente, pero aparece el mensaje de error: WindowsError: [Error 3] The system cannot find the path specified: '/test123/*.*'

¿Alguien tiene una idea de cómo resolver este problema? ¡Gracias de antemano!

 import os, time from ftplib import FTP ftp = FTP('127.0.0.1') print "Automated FTP Maintainance" print 'Logging in.' ftp.login('admin', 'admin') # This is the directory that we want to go to path = 'test123' print 'Changing to:' + path ftp.cwd(path) files = ftp.retrlines('LIST') print 'List of Files:' + files #--everything works fine until here!... #--The Logic which shall delete the files after the are 7 days old-- now = time.time() for f in os.listdir(path): if os.stat(f).st_mtime < now - 7 * 86400: if os.path.isfile(f): os.remove(os.path.join(path, f)) except: exit ("Cannot delete files") print 'Closing FTP connection' ftp.close() 

DE ACUERDO. Suponiendo que su servidor FTP admita el comando MLSD , MLSD un módulo con el siguiente código (este es el código de un script que uso para sincronizar un sitio FTP remoto con un directorio local):

código del módulo

 # for python ≥ 2.6 import sys, os, time, ftplib import collections FTPDir= collections.namedtuple("FTPDir", "name size mtime tree") FTPFile= collections.namedtuple("FTPFile", "name size mtime") class FTPDirectory(object): def __init__(self, path='.'): self.dirs= [] self.files= [] self.path= path def getdata(self, ftpobj): ftpobj.retrlines('MLSD', self.addline) def addline(self, line): data, _, name= line.partition('; ') fields= data.split(';') for field in fields: field_name, _, field_value= field.partition('=') if field_name == 'type': target= self.dirs if field_value == 'dir' else self.files elif field_name in ('sizd', 'size'): size= int(field_value) elif field_name == 'modify': mtime= time.mktime(time.strptime(field_value, "%Y%m%d%H%M%S")) if target is self.files: target.append(FTPFile(name, size, mtime)) else: target.append(FTPDir(name, size, mtime, self.__class__(os.path.join(self.path, name)))) def walk(self): for ftpfile in self.files: yield self.path, ftpfile for ftpdir in self.dirs: for path, ftpfile in ftpdir.tree.walk(): yield path, ftpfile class FTPTree(FTPDirectory): def getdata(self, ftpobj): super(FTPTree, self).getdata(ftpobj) for dirname in self.dirs: ftpobj.cwd(dirname.name) dirname.tree.getdata(ftpobj) ftpobj.cwd('..') 

caso de directorio único

Si desea trabajar en los archivos de un directorio, puede:

 import ftplib, time quite_old= time.time() - 7*86400 # seven days site= ftplib.FTP(hostname, username, password) site.cwd(the_directory_to_work_on) # if it's '.', you can skip this line folder= FTPDirectory() folder.getdata(site) # get the filenames for path, ftpfile in folder.walk(): if ftpfile.mtime < quite_old: site.delete(ftpfile.name) 

Esto debería hacer lo que quieras.

Un directorio y sus descendientes.

Ahora, si esto debería funcionar de forma recursiva, tendrá que hacer los siguientes dos cambios en el código para el "caso de directorio único":

 folder= FTPTree() 

y

 site.delete(os.path.join(path, ftpfile.name)) 

Posible advertencia

Los servidores con los que he trabajado no tenían ningún problema con las rutas relativas en los comandos STOR y DELE , así que site.delete con una ruta relativa también funcionó. Si su servidor FTP requiere nombres de archivos sin path , primero debe .cwd a la path provista, .delete el ftpfile.name y luego .cwd a la carpeta base.

Tuve que hacer esto y me tomó un tiempo, pensé que podía ahorrar el tiempo de alguien aquí. Estamos usando python con el módulo ftputil instalado:

 #! /usr/bin/python import time import ftputil host = ftputil.FTPHost('ftphost.com', 'username', 'password') mypath = 'ftp_dir' now = time.time() host.chdir(mypath) names = host.listdir(host.curdir) for name in names: if host.path.getmtime(name) < (now - (7 * 86400)): if host.path.isfile(name): host.remove(name) print 'Closing FTP connection' host.close() 

Bien, en lugar de analizar el código que has publicado, aquí hay un ejemplo que podría ponerte en el camino correcto.

 from ftplib import FTP import re pattern = r'.* ([AZ|az].. .. .....) (.*)' def callback(line): found = re.match(pattern, line) if (found is not None): print found.groups() ftp = FTP('myserver.wherever.com') ftp.login('elvis','presley') ftp.cwd('testing123') ftp.retrlines('LIST',callback) ftp.close() del ftp 

Ejecútelo y obtendrá una salida como esta, que debería ser un comienzo hacia lo que está tratando de lograr. Para finalizar, deberá analizar el primer resultado en una fecha y hora, compararlo con “ahora” y usar http://ftp.delete () para deshacerse del archivo remoto si es demasiado antiguo.

 >>> ('May 16 13:47', 'Thumbs.db') ('Feb 16 17:47', 'docs') ('Feb 23 2007', 'marvin') ('May 08 2009', 'notes') ('Aug 04 2009', 'other') ('Feb 11 18:24', 'ppp.xml') ('Jan 20 2010', 'reports') ('Oct 10 2005', 'transition') >>> 

Bueno, parece que el error que está viendo tiene que ver con el hecho de que está intentando eliminar el directorio ‘test123’ de su máquina local, no del sitio FTP. Los documentos FTP tienen un método llamado eliminar , y eso es lo que querría usar para eliminar el archivo. En cuanto a probar si algo tiene o no 7 días de antigüedad o no, es posible que tenga que bajar esos archivos del FTP temporalmente, luego verifique los tiempos de modificación antes de usar http://FTP.delete.

¿En qué sistema operativo estás ejecutando? La ruta del archivo /test123/*.* es de estilo Unix, pero el mensaje dice WindowsError . ¿Está tomando la salida de un comando ftp LIST, que está en estilo Unix, y está tratando de usarlo literalmente en un script de Windows?