По работе возникла необходимость следить за обновлениями каталогов на удаленном FTP. Сам по себе список достаточно большой вложенности, поэтому обходить их вручную не было никакого удовольствия. Желание всё это автоматизировать вылилось в написание питонического скрипта.

Входные параметры:
  • DAYS - количество дней за которые проверять обновления;
  • HOST - ftp-сервер;
  • INFILE - пути к каталогам в которых проверять обновления;
  • OUTFILE - выходной файл, файлы которые были обновлены за последние DAYS дней.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import ftplib, datetime, re, sys, time

DAYS = 7
HOST = 'ftp.gnu.org'
INFILE = "folderlist.txt"
OUTFILE = "fresh_files.txt"

def get_file_info(ftp_file_row=""):
    now = datetime.datetime.now()
    fileinfo = re.findall("(d?).*?((?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"
                       "*?[0-3][0-9] *?[0-9][0-9]:?[0-9][0-9]) *(.+)", ftp_file_row)[0]
    isDir = fileinfo[0] == "d"
    ftpDate = fileinfo[1]
    filename = fileinfo[2]
    ftpDate = " ".join(ftpDate.split())
    if ":" in ftpDate:
        fileDate = datetime.datetime.strptime(ftpDate, "%b %d %H:%M")
        fileDate = fileDate.replace(year=2014)
        if fileDate > now: fileDate = fileDate.replace(year=2013)
    else:
        fileDate = datetime.datetime.strptime(ftpDate, "%b %d %Y")
    return isDir, fileDate, filename

def is_date_in_range(adate, adays=7):
    now = datetime.datetime.now()
    return adate > now - datetime.timedelta(days=adays)

def get_ftp_fresh_files(pathList, serverAdr):
    freshFilesList = []
    ftp = ftplib.FTP(serverAdr)
    ftp.login()
    ftp.cwd("/")
    stack = list(pathList)
    while stack:
        # time.sleep(0.5)
        curPath = stack.pop()
        if curPath == "/": curPath = ""
        print curPath
        dirContens = []
        ftp.dir(curPath, lambda s: dirContens.append(get_file_info(s)))
        for isDir, fileDate, fileName in dirContens:
            if not (fileName == ".." or fileName == "."):
                if isDir: stack.append(curPath+"/"+fileName)
                if is_date_in_range(fileDate, DAYS):
                    freshFilesList.append((fileDate, curPath+"/"+fileName))
    ftp.quit()
    return freshFilesList

def main():
    folderlist = []
    using open(INFILE,"r") as f:
        for line in f:
            folder = "".join(line.split("\n"))
            if folder: folderlist.append(folder)
    print "Start getting files"
    l = get_ftp_fresh_files(folderlist, HOST)
    print "Done!"
    l = sorted(l, key=lambda x:x[0], reverse=True)
    using open(OUTFILE, "wb") as outfile:
        for row in l:
            outfile.write(row[0].strftime("%d.%m.%Y %H:%M") + "  " + row[1] + "\n")
    return 0

if __name__ == "__main__":
    main()