如何使用ftplib检查远程ftp上的文件是否是文件夹?
我现在最好的方法是做一个nlst,并遍历每个文件的调用大小,如果文件出错那么它是一个文件夹?
有更好的方法吗?我无法解析列表的输出,因为有大约十几个不同的ftp服务器(很多很老。)
我该怎么办?
答案 0 :(得分:7)
FTP是一个非常基本的协议,并且没有内置的协议查询允许您获取每个节点的类型(文件,目录),因此像您找到的启发式解决方案是唯一的解决方案。
如果获得每个节点的大小不起作用,也许您应该考虑在每个节点上调用FTP.nlst()
:那些错误输出将是文件而不是dirs。
答案 1 :(得分:5)
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")
答案 2 :(得分:4)
FTP.dir
返回一个目录列表,您可以使用回调函数进行解析,以确定它是否是目录。例如,像这样:
def parse(line):
if line[0] == 'd':
print(line.rpartition(' ')[2]) # gives you the name of a directory
ftp.dir(parse)
答案 3 :(得分:3)
您可以使用MLST命令:
import ftplib
f = ftplib.FTP()
f.connect("localhost")
f.login()
print f.sendcmd('MLST /')
反对pyftpdlib server上面的代码打印:
250-Listing "/":
modify=20111212124834;perm=el;size=12288;type=dir;unique=807g100001; /
250 End MLST.
你需要做的是解析该字符串并查找“type = dir”或“type = cdir”(当前目录,如“。”)或“type = pdir”(父目录,如“.. “)通过正则表达式。 如果得到匹配,则表示提供的路径引用目录。
答案 4 :(得分:2)
def is_file(filename):
return ftp.size(filename) is not None
这是有效的,因为如果ftp.size是目录,则返回None。
答案 5 :(得分:1)
我在处理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!"
答案 6 :(得分:1)
这是我用于查找给定目录中的目录的内容。我将目录名称作为集合返回,因为我稍后在程序中使用集合,但您可以在结尾处保留集合创建并将目录名称作为列表,元组等返回。
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
答案 7 :(得分:0)
def is_file(filename):
current = ftp.pwd()
try:
ftp.cwd(filename)
except:
ftp.cwd(current)
return True
ftp.cwd(current)
return False
这是另一种解决方案。写出来的一半我意识到它有问题。如果您无权更改文件夹,则会将其作为文件读取。如果您可以访问任何文件夹,它将起作用。
我仍然发布它,因为它可能会提供一些想法。
答案 8 :(得分:0)
我找到了一个解决方案,但它可能不是最好的,我觉得它对你有帮助。
> def isfile(remote_name):
> try:
> ftp.sendcmd('MDTM ' + remote_name)
> except:
> return False
> else:
> return True
如果' remote_name'此功能将返回TRUE。是常规文件,否则返回False。
答案 9 :(得分:0)
我的整个解决方案如下:
def is_file(filename):
try:
ftp.cwd(filename)
except Exception as e:
if "550" in e:
return True
return False
答案 10 :(得分:0)
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'
答案 11 :(得分:0)
def _get_file_type(self, path):
"""
Returns string parsed from MLST command
"""
try:
return_str = self.ftp.sendcmd('MLST ' + path)
except BaseException as e:
raise BaseException("No such file or directory")
c = re.search('Type=(dir|file);', return_str)
try:
filetype = c.group(1)
except AttributeError as e:
raise BaseException("Unable to parse")
return filetype
def is_file(self,path):
"""
Returns if a filepath is a file
"""
filetype = self._get_file_type(path)
if filetype == 'file':
return True
return False
答案 12 :(得分:0)
如果True
是文件,则此函数返回object
,否则返回False
。
def _is_file(FTP, object):
if FTP.nlst(object) == [object]:
return True
else:
return False
用法示例:
import ftplib
with ftplib.FTP(host=ftp_link, user=ftp_username, passwd=ftp_password) as FTP:
if _is_file(FTP, object='/path/filename.extention'):
print(object, 'is file!')
else:
print(object, 'is directory!')
FTP.nlst()如何工作?
FTP.nlst(object)
是文件,[object]
返回object
。FTP.nlst(object)
是一个空文件夹,object
返回一个空列表。FTP.nlst(object)
是包含文件或目录的文件夹,则object
返回字符串列表。答案 13 :(得分:0)
如果要检查路径是否属于文件或目录,最好的解决方案是您已经提到的内容:
ftp = FTP()
ftp.connect(host, port)
ftp.login(user, pass)
# returns True if the path belongs to a file and False if it's a folder
def is_file(path):
try:
ftp.size(path)
return True
except:
return False
但是,如果要获取文件夹内文件或文件夹的列表,则可以使用mlsd
方法。此方法返回一个字典,它的键是子元素的名称,其值是另一个字典,显示每个元素的属性,在每个值中,都有一个名为type
的键,它显示元素的类型:
cdir
:当前目录(!?)(属于.
键)
pdir
:父目录(它属于..
键)
dir
:目录。
file
:文件!
例如,此函数返回一个元组,其中包含文件列表和目录列表:
def ls(path):
files_list = []
directories_list = []
for k, v in ftp.mlsd(path):
if v['type'] == 'file':
files_list.append(k)
elif v['type'] == 'dir':
directories_list.append(k)
return files_list, directories_list
答案 14 :(得分:-3)
所有文件都有一个扩展名,因此通过使用split(&#39;。&#39;),可以将其分成大小为2的列表。对于目录,使用split后列表的大小为1(& #39;&#39)。因此,通过检查列表的大小,我们可以识别它的文件或目录。
os.chdir(r"path")
ftp = ftplib.FTP('ftp.some.server')
ftp.login('username','password')
filelist=ftp.nlst()
for file in filelist:
fildir=file.split('.')
filsize=len(fildir)
if(filsize>1):
ftp.retrbinary('RETR %s' %file, open(file, 'wb').write)
ftp.close()