Python FTP按日期获取最新文件

19 投票
5 回答
28456 浏览
提问于 2025-04-17 10:59

我正在使用ftplib来连接一个ftp网站。我想获取最近上传的文件并下载它。我可以连接到ftp服务器并列出文件,我还把这些文件放进了一个列表,并且把datefield转换过了。有没有什么函数或模块可以获取最近的日期,并从列表中输出整行信息呢?

#!/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()

已解决:

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

有一个问题,就是能否从字典中获取第一个元素?我在这里做的是for循环只运行了一次就退出了,这样我得到了第一个排序的值,这样是可以的,但我觉得这样做不是一个好的实践……

5 个回答

7

你为什么不使用下一个目录选项呢?

ftp.dir('-t',data.append)

使用这个选项后,文件列表会按照时间从最新到最旧排列。然后你只需要获取列表中的第一个文件就可以下载了。

31

对于那些想要找到文件夹中最新文件的完整解决方案的人:

MLSD

如果你的FTP服务器支持MLSD命令,那么解决方案就很简单:

entries = list(ftp.mlsd())
entries.sort(key = lambda entry: entry[1]['modify'], reverse = True)
latest_name = entries[0][0]
print(latest_name)

LIST

如果你只能依赖一个过时的LIST命令,那么你需要解析它返回的特定格式的列表。

常见的*nix格式的列表大概是这样的:

-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

对于这样的列表,下面的代码可以使用:

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)

这种方法有点脆弱。


MDTM

一个更可靠但效率低下的方法是使用MDTM命令来获取单个文件或文件夹的时间戳:

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)

想看代码的另一种版本,可以参考@Paulo的回答


非标准的 -t 选项

一些FTP服务器支持一个非标准的-t选项,用于NLST(或LIST)命令。

lines = ftp.nlst("-t")

latest_name = lines[-1]

可以查看如何按修改时间获取FTP文件夹中的文件


下载找到的文件

无论你使用哪种方法,一旦你得到了latest_name,就可以像下载其他文件一样下载它:

with open(latest_name, 'wb') as f:
    ftp.retrbinary('RETR '+ latest_name, f.write)

另见

6

在使用 NLST 的时候,就像马丁·普里克里尔的回答中提到的,你应该使用 sorted 方法:

ftp = FTP(host="127.0.0.1", user="u",passwd="p")
ftp.cwd("/data")
file_name = sorted(ftp.nlst(), key=lambda x: ftp.voidcmd(f"MDTM {x}"))[-1]

撰写回答