【问题标题】:Python FTP get the most recent file by datePython FTP 按日期获取最新文件
【发布时间】:2012-02-17 22:07:38
【问题描述】:

我正在使用 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 循环只运行一次并退出,从而为我提供了第一个排序值,这很好,但我认为以这种方式执行它不是一个好习惯..

【问题讨论】:

  • 是否可以下载最新添加的 .csv 文件而不是一般的最新文件?
  • FTP 以明文形式发送密码。 SFTP 更安全(通过 SSH 的 FTP,pip install pysftp)但 not as fast 作为 FTPS(通过 SSL/TLS 的 FTP),就像使用 ftplib.FTP_TLS() 而不是 ftplib.FTP() 一样简单。

标签: python linux ftp ftplib


【解决方案1】:

如果您的列表中有time.struct_time 中的所有日期(strptime 将给您这个),那么您所要做的就是sort 列表。

这是一个例子:

#!/usr/bin/python

import time

dates = [
    "Jan 16 18:35 2012",
    "Aug 16 21:14 2012",
    "Dec 05 22:27 2012",
    "Jan 22 19:42 2012",
    "Jan 24 00:49 2012",
    "Dec 15 22:41 2012",
    "Dec 13 01:41 2012",
    "Dec 24 01:23 2012",
    "Jan 21 00:35 2012",
    "Jan 16 18:35 2012",
]

def main():
    datelist = []
    for date in dates:
        date = time.strptime(date, '%b %d %H:%M %Y')
        datelist.append(date)

    print datelist
    datelist.sort()
    print datelist

if __name__ == '__main__':
    main()

【讨论】:

  • 我创建了另一个列表,看到更新,似乎theres someproblem with sort the dictionary..
  • 我知道您实际上在回答 OP 的问题。但总的来说,如果 OP 只查找一个最新文件,那么首先构建日期列表是一种过度杀伤和内存浪费。只需在第一个循环中找到最新的文件即可。此外,还有其他更有效的解决方案。见my answer
【解决方案2】:

我不知道你的 ftp 怎么样,但你的例子对我不起作用。我更改了一些与日期排序部分相关的行:

    import sys
    from ftplib import FTP
    import os
    import socket
    import time

    # Connects to the ftp
    ftp = FTP(ftpHost)
    ftp.login(yourUserName,yourPassword)
    data = []
    datelist = []
    filelist = []
    ftp.dir(data.append)
    for line in data:
      col = line.split()
      datestr = ' '.join(line.split()[5:8])
      date = time.strptime(datestr, '%b %d %H:%M')
      datelist.append(date)
      filelist.append(col[8])
    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:
        ftp.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
    ftp.quit()

【讨论】:

    【解决方案3】:

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

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

    使用此选项,文件列表按时间从最新到最旧排序。然后只需检索列表中的第一个文件即可下载。

    【讨论】:

    • 毫无价值,-t 开关是专有的(实际上违反了 FTP 规范)。虽然它得到了相当广泛的支持,但它并不是普遍的。有关详细信息的链接,请参阅 my answer
    【解决方案4】:

    对于那些寻找在文件夹中查找最新文件的完整解决方案的人:

    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 命令,则必须解析它返回的专有列表。

    常见的 *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)
    

    有关代码的替代版本,请参阅the answer by @Paulo


    非标准-t开关

    一些 FTP 服务器支持 NLST(或 LIST)命令的专有非标准 -t 开关。

    lines = ftp.nlst("-t")
    
    latest_name = lines[-1]
    

    How to get files in FTP folder sorted by modification time


    下载找到的文件

    无论您使用哪种方法,一旦您拥有latest_name,您就可以将其作为任何其他文件下载:

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

    另见

    【讨论】:

      【解决方案5】:

      NLST,如 Martin Prikryl 的回复所示, 你应该使用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]
      

      【讨论】:

      • 不错的短代码。它也相当可靠。但正如my answer 所说,这非常低效,特别是如果文件夹中有很多文件文件。
      猜你喜欢
      • 2011-03-21
      • 1970-01-01
      • 1970-01-01
      • 2021-04-16
      • 1970-01-01
      • 2021-07-06
      • 2019-01-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多