Как удалить файлы с помощью скрипта Python с FTP-сервера старше 7 дней? - PullRequest
9 голосов
/ 19 мая 2010

Я хотел бы написать скрипт на Python, который позволит мне удалять файлы с FTP-сервера после того, как они достигли определенного возраста. Я подготовил нижеприведенный текст, но он выдает сообщение об ошибке: 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()

Ответы [ 5 ]

9 голосов
/ 25 июня 2010

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

один каталог

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

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)

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

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

Теперь, если это должно сработать рекурсивно, вам придется выполнить следующие два изменения в коде для «случая единого каталога»:

folder= FTPTree()

и

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

Возможное предупреждение

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

3 голосов
/ 16 июля 2013

Я должен был сделать это, и это заняло некоторое время, подумав, что я мог бы сэкономить кому-то время здесь. Мы используем python с установленным модулем ftputil:

#! /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()
2 голосов
/ 19 мая 2010

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

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

Запустите его, и вы получите что-то вроде этого, что должно стать началом к ​​тому, чего вы пытаетесь достичь. Чтобы закончить, вам нужно проанализировать первый результат в datetime, сравнить его с «сейчас» и использовать 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')
>>> 
0 голосов
/ 19 мая 2010

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

0 голосов
/ 19 мая 2010

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

...