9

我想编写一个 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()
4

5 回答 5

10

好的。假设您的 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我使用过的服务器在andDELE命令中的相对路径没有任何问题,因此site.delete相对路径也可以使用。如果您的 FTP 服务器需要无路径文件名,您应该首先.cwd使用path提供.delete的普通文件名,ftpfile.name然后.cwd返回基本文件夹。

于 2010-06-24T22:51:07.377 回答
4

我不得不这样做,花了一段时间,以为我可以在这里节省别人的时间。我们正在使用安装了 ftputil 模块的 python:

#! /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()
于 2013-07-15T20:07:42.240 回答
2

好的,与其进一步分析您发布的代码,这里有一个示例,它可能会让您走上正确的轨道。

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')
>>> 
于 2010-05-19T17:52:07.603 回答
0

Well, it looks like the error you are seeing has to do with the fact that you are trying to remove the 'test123' directory from your local machine, not the FTP site. The FTP docs have a method called delete, and that's what you'd want to use to remove the file. As far as testing whether or not something is 7 days old or not, you might actually have to pull those files down from the FTP temporarily then check the modify times before using FTP.delete.

于 2010-05-19T16:18:55.907 回答
0

你在什么操作系统上运行?文件路径/test123/*.*是 Unix 风格的,但消息显示WindowsError. 您是否正在获取 Unix 风格的 ftp LIST 命令的输出,并尝试在 Windows 脚本中逐字使用它?

于 2010-05-19T17:16:43.447 回答