我该如何使用ftplib检查远程ftp上的文件是否是文件夹?
目前最好的方法是进行nlst操作,并循环调用每个文件的size函数,如果文件出错,则它就是一个文件夹?
有没有更好的方法?我不能解析list的输出,因为有大约十几个不同的ftp服务器(许多非常老旧)。
我应该怎么办?
在ftplib中没有"isdir"和"isfile"的定义。如果您不必使用ftplib,我建议您使用ftputil。
首先,您需要安装ftputil包。为此,请使用以下命令:python -m pip install ftputil
。安装完成后,您可以将该库导入到您的代码中。我认为这已经足够解释了。那么,让我们进入实现:
import ftputil
with ftputil.FTPHost("host", "username", "password") as ftp_host:
ftp_host.chdir("/directory/")
list = ftp_host.listdir(ftp_host.curdir)
for fname in list:
if ftp_host.path.isdir(fname):
print(fname + " is a directory")
else:
print(fname + " is not a directory")
FTP是一种相当基础的协议,没有内置协议查询可以让您获取每个节点的类型(文件、目录),因此像您找到的这样的启发式方法是唯一的解决方案。
如果获取每个节点的大小不起作用,也许您应该考虑在这些节点上调用FTP.nlst()
:那些出错的将是文件而不是目录。
import ftplib
f = ftplib.FTP()
f.connect("localhost")
f.login()
print f.sendcmd('MLST /')
对于pyftpdlib服务器,上面的代码将打印出:
250-Listing "/":
modify=20111212124834;perm=el;size=12288;type=dir;unique=807g100001; /
250 End MLST.
FTP.dir
返回一个目录列表,你可以使用回调函数解析它以确定它是否为目录。例如像这样:
def parse(line):
if line[0] == 'd':
print(line.rpartition(' ')[2]) # gives you the name of a directory
ftp.dir(parse)
def is_file(filename):
return ftp.size(filename) is not None
def is_file(filename):
current = ftp.pwd()
try:
ftp.cwd(filename)
except:
ftp.cwd(current)
return True
ftp.cwd(current)
return False
我在处理ftplib时使用过这个:
import ftplib
from ftplib import FTP
ftp=FTP("ftp address")
ftp.login("user","password")
path = "/is/this/a/file/or/a/folder/"
try:
ftp.cwd(path)
print "it's a folder!"
except ftplib.error_perm:
print "it's not a folder!"
def get_directories(ftp_server):
"""
Returns a set of directories in the current directory on the FTP server
Stdout output of ftp_server.dir() is redirected to an IO object and then
reset, because ftp_server.dir() only prints its results to stdout.
@param ftp_server: Open connection to FTP server
@return: Set of directory names
"""
# Redirect stdout
old_stdout = sys.stdout
sys.stdout = new_stdout = StringIO()
# Get directory listing
ftp_server.dir()
# Reset stdout
sys.stdout = old_stdout
directory_listing = new_stdout.getvalue().split("\n")
# Directories are listed starting with "d" for "directory"
only_directories = (x for x in directory_listing if x.startswith("d"))
# This only deals with directory names without spaces.
directory_names = set(dirname.split()[-1] for dirname in only_directories)
return directory_names
我找到了一个解决方案,但可能不是最好的,我认为它对你可能会有帮助。
> def isfile(remote_name):
> try:
> ftp.sendcmd('MDTM ' + remote_name)
> except:
> return False
> else:
> return True
如果'remote_name'是一个普通文件,此函数将返回TRUE,否则返回False。
ftp_conn = FTP(host=host_name, user=user_name, passwd=password, acct='', timeout=None, source_address=None)
ftp_conn.cwd(path_ftp)
for data_dir in ftp_conn.mlsd():
print(data_dir)
输出:
('3', {'modify': '20170719134928', 'perm': 'flcdmpe', 'type': 'dir', 'unique': '804U485826E', 'unix.group': '10000', 'unix.mode': '0755', 'unix.owner': '10754'})
see 'type': 'dir'