Как удалить файлы со сценарием Python от FTP-сервера, которые являются более старыми, чем 7 дней?

Я хотел бы записать сценарий Python, который позволяет мне удалять файлы из FTP-сервера после того, как они достигли определенного возраста. Я подготовил scipt ниже, но он бросает сообщение об ошибке: WindowsError: [Error 3] The system cannot find the path specified: '/test123/*.*'

У кого-то есть идея, как решить этот вопрос?Заранее спасибо!

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()
9
задан Brian Tompsett - 汤莱恩 6 July 2015 в 19:46
поделиться

4 ответа

Хорошо, вместо того, чтобы анализировать код, который вы разместили дальше, вот пример, который может направить вас на правильный путь.

from ftplib import FTP
import re

pattern = r'.* ([A-Z|a-z].. .. .....) (.*)'

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

Запустите его, и вы получите что-то вроде этого, что должно стать началом того, чего вы пытаетесь достичь. Чтобы завершить его, вам нужно преобразовать первый результат в дату и время, сравнить его с «сейчас» и использовать ftp.delete (), чтобы избавиться от удаленного файла, если он слишком старый.

>>> 
('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')
>>> 
2
ответ дан 4 December 2019 в 14:26
поделиться

На какой ОС вы работаете? Путь к файлу / test123 /*.* выполнен в стиле Unix, но в сообщении указано WindowsError . Вы берете вывод команды ftp LIST в стиле Unix и пытаетесь дословно использовать его в сценарии Windows?

0
ответ дан 4 December 2019 в 14:26
поделиться

Ну, похоже, что ошибка, которую вы видите, связана с тем, что вы пытаетесь удалить каталог 'test123' с вашего локального компьютера, а не с FTP-сайта. В документах FTP есть метод с именем delete, и это то, что вы хотите использовать для удаления файла. Что касается проверки того, есть ли чему-то 7 дней или нет, вам, возможно, придется временно извлечь эти файлы из FTP, а затем проверить время изменения перед использованием FTP.delete.

0
ответ дан 4 December 2019 в 14:26
поделиться

OK. Предполагая, что ваш FTP-сервер поддерживает команду MLSD, создайте модуль со следующим кодом (это код из скрипта, который я использую для синхронизации удаленного FTP-сайта с локальным каталогом):

код модуля

# 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('..')

single directory case

Если вы хотите работать с файлами каталога, вы можете:

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)

Это должно сделать то, что вы хотите.

каталог и его потомки

Теперь, если это должно работать рекурсивно, вам придется сделать следующие два изменения в коде для "single directory case":

folder= FTPTree()

и

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

Возможная оговорка

Серверы, с которыми я работал, не имели проблем с относительными путями в командах STOR и DELE, поэтому site.delete с относительным путем тоже работает. Если ваш FTP-сервер требует имен файлов без путей, вам следует сначала .cwd в указанный путь, .delete простой ftpfile.name, а затем .cwd обратно в базовую папку.

9
ответ дан 4 December 2019 в 14:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: