pysftp listdir_attr在含文件目录返回空值问题求助
SFTP扫描工具子目录
listdir_attr返回空的排查方案 问题描述
我开发了一款用于扫描SFTP服务器并进行数据统计分析的小工具,代码在多数服务器上运行正常,但在某一特定服务器上出现异常:仅能列出顶层目录,进入子目录后listdir_attr返回空值,无任何报错信息。排查了连接选项但未发现相关影响因素,求问类似问题的排查方向。
工具代码
import pysftp import os class Connector: def __init__(self, host: str, user: str, password: str, port: int = 22, root: str = "."): ops = pysftp.CnOpts() ops.hostkeys = None self.root = root self.client = pysftp.Connection(host=host, username=user, password=password, port=port, cnopts=ops) self.stats = list() def __looper(self, folder): for f in self.client.listdir_attr(folder): f.attr["path"] = folder f.attr["props"] = f.longname[:10] self.stats.append(f) if f.longname.startswith("d"): self.__looper(os.path.join(folder, f.filename)) def build_stats(self): self.__looper(self.root) self.client.close() return self.stats
排查方向与解决方案
- 权限验证:先用FileZilla等通用SFTP客户端登录目标服务器,手动尝试进入子目录并查看内容。如果客户端也无法列出子目录,说明是服务器端对当前用户的子目录权限限制,联系管理员调整权限即可。
- 路径分隔符问题:代码中用
os.path.join拼接路径,该方法会随系统环境生成不同分隔符(Windows下是\),而多数SFTP服务器只认可/作为路径分隔符。替换成手动拼接:f"{folder}/{f.filename}",避免系统依赖的格式问题。 - 绕过pysftp封装:部分定制化/老旧SFTP服务器可能与pysftp的
listdir_attr实现不兼容,改用paramiko(pysftp的底层依赖)的原生方法拆分逻辑:先通过listdir获取文件名,再逐个调用stat获取属性,示例如下:def __looper(self, folder): filenames = self.client.listdir(folder) for filename in filenames: full_path = f"{folder}/{filename}" attr = self.client.stat(full_path) # 构造兼容原逻辑的对象结构 sftp_file = type('SFTPFile', (), { 'filename': filename, 'longname': f"{ 'd' if attr.st_mode & 0o40000 else '-' }rwxrwxrwx", 'attr': attr.__dict__ })() sftp_file.attr["path"] = folder sftp_file.attr["props"] = sftp_file.longname[:10] self.stats.append(sftp_file) if attr.st_mode & 0o40000: # 判断是否为目录 self.__looper(full_path) - 查看服务器日志:联系服务器管理员查看SFTP服务的运行日志,确认是否存在针对子目录列表请求的拦截、错误记录或特殊配置限制。
- 特殊字符目录验证:如果子目录名称包含空格、非ASCII字符,打印拼接后的路径检查格式是否正确,必要时对文件名做编码处理后再拼接路径。
内容的提问来源于stack exchange,提问作者abolotnov
相关产品推荐
相关产品推荐

