sqr*_*ram 4 python ftp traversal
我试图从FTP服务器获取所有目录的名称,并将它们按层次顺序存储在多维列表或字典中
例如,包含以下结构的服务器:
/www/
mysite.com
images
png
jpg
Run Code Online (Sandbox Code Playgroud)
在脚本的最后,会给我一个列表,如
['/www/'
['mysite.com'
['images'
['png'],
['jpg']
]
]
]
Run Code Online (Sandbox Code Playgroud)
我试过使用像这样的递归函数:def traverse(dir):FTP.dir(dir,traverse)
FTP.dir以这种格式返回行:
drwxr-xr-x 5 leavesc1 leavesc1 4096 Nov 29 20:52 mysite.com
Run Code Online (Sandbox Code Playgroud)
所以做行[56:]会给我一个目录名称(mysite.com).我在递归函数中使用它.
但我无法让它发挥作用.我尝试了很多不同的方法,无法让它发挥作用.很多FTP错误(无法找到目录 - 这是一个逻辑问题,有时服务器返回意外错误,没有留下日志,我无法调试)
底线问题: 如何从FTP服务器获取分层目录列表?
这是一个天真而缓慢的实现.它很慢,因为它尝试CWD到每个目录条目,以确定它是一个目录或文件,但这是有效的.可以通过解析LIST命令输出来优化它,但这是强烈依赖于服务器实现的.
import ftplib
def traverse(ftp, depth=0):
"""
return a recursive listing of an ftp server contents (starting
from the current directory)
listing is returned as a recursive dictionary, where each key
contains a contents of the subdirectory or None if it corresponds
to a file.
@param ftp: ftplib.FTP object
"""
if depth > 10:
return ['depth > 10']
level = {}
for entry in (path for path in ftp.nlst() if path not in ('.', '..')):
try:
ftp.cwd(entry)
level[entry] = traverse(ftp, depth+1)
ftp.cwd('..')
except ftplib.error_perm:
level[entry] = None
return level
def main():
ftp = ftplib.FTP("localhost")
ftp.connect()
ftp.login()
ftp.set_pasv(True)
print traverse(ftp)
if __name__ == '__main__':
main()
Run Code Online (Sandbox Code Playgroud)
这是对我有用的 Python 3 脚本的初稿。比打电话快多了cwd()。传入服务器、端口、目录、用户名和密码作为参数。我将输出保留为列表,作为读者的练习。
import ftplib
import sys
def ftp_walk(ftp, dir):
dirs = []
nondirs = []
for item in ftp.mlsd(dir):
if item[1]['type'] == 'dir':
dirs.append(item[0])
else:
nondirs.append(item[0])
if nondirs:
print()
print('{}:'.format(dir))
print('\n'.join(sorted(nondirs)))
else:
# print(dir, 'is empty')
pass
for subdir in sorted(dirs):
ftp_walk(ftp, '{}/{}'.format(dir, subdir))
ftp = ftplib.FTP()
ftp.connect(sys.argv[1], int(sys.argv[2]))
ftp.login(sys.argv[4], sys.argv[5])
ftp_walk(ftp, sys.argv[3])
Run Code Online (Sandbox Code Playgroud)