わかった。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)
これはあなたが望むことをするはずです。
ディレクトリとその子孫
これが再帰的に機能する場合は、「単一ディレクトリの場合」のコードで次の2つの変更を行う必要があります。
folder= FTPTree()
と
site.delete(os.path.join(path, ftpfile.name))
考えられる警告
STOR
私が使用したサーバーでは、コマンドとDELE
コマンドの相対パスに問題がなかったためsite.delete
、相対パスでも機能しました。FTPサーバーでパスレスファイル名が必要な場合は、最初.cwd
にpath
提供され.delete
たプレーンftpfile.name
に.cwd
移動してから、ベースフォルダーに戻る必要があります。