如何让Python检查ftp目录是否存在?

时间:2021-12-04 00:03:58

I'm using this script to connect to sample ftp server and list available directories:

我正在使用此脚本连接到示例ftp服务器并列出可用目录:

from ftplib import FTP
ftp = FTP('ftp.cwi.nl')   # connect to host, default port (some example server, i'll use other one)
ftp.login()               # user anonymous, passwd anonymous@
ftp.retrlines('LIST')     # list directory contents
ftp.quit()

How do I use ftp.retrlines('LIST') output to check if directory (for example public_html) exists, if it exists cd to it and then execute some other code and exit; if not execute code right away and exit?

如何使用ftp.retrlines('LIST')输出来检查目录(例如public_html)是否存在,是否存在cd,然后执行其他一些代码并退出;如果不立即执行代码并退出?

7 个解决方案

#1


Nslt will list an array for all files in ftp server. Just check if your folder name is there.

Nslt将为ftp服务器中的所有文件列出一个数组。只需检查您的文件夹名称是否存在。

from ftplib import FTP 
ftp = FTP('yourserver')
ftp.login('username', 'password')

folderName = 'yourFolderName'
if folderName in ftp.nlst():
    #do needed task 

#2


you can use a list. example

你可以使用一个清单。例

import ftplib
server="localhost"
user="user"
password="test@email.com"
try:
    ftp = ftplib.FTP(server)    
    ftp.login(user,password)
except Exception,e:
    print e
else:    
    filelist = [] #to store all files
    ftp.retrlines('LIST',filelist.append)    # append to list  
    f=0
    for f in filelist:
        if "public_html" in f:
            #do something
            f=1
    if f==0:
        print "No public_html"
        #do your processing here

#3


You can send "MLST path" over the control connection. That will return a line including the type of the path (notice 'type=dir' down here):

您可以通过控制连接发送“MLST路径”。这将返回一行,包括路径的类型(注意'type = dir'在这里):

250-Listing "/home/user":
 modify=20131113091701;perm=el;size=4096;type=dir;unique=813gc0004; /
250 End MLST.

Translated into python that should be something along these lines:

转换成python应该是这些方面的东西:

import ftplib
ftp = ftplib.FTP()
ftp.connect('ftp.somedomain.com', 21)
ftp.login()
resp = ftp.sendcmd('MLST pathname')
if 'type=dir;' in resp:
    # it should be a directory
    pass

Of course the code above is not 100% reliable and would need a 'real' parser. You can look at the implementation of MLSD command in ftplib.py which is very similar (MLSD differs from MLST in that the response in sent over the data connection but the format of the lines being transmitted is the same): http://hg.python.org/cpython/file/8af2dc11464f/Lib/ftplib.py#l577

当然,上面的代码不是100%可靠,需要一个“真正的”解析器。您可以在ftplib.py中查看MLSD命令的实现,它非常相似(MLSD与MLST的不同之处在于通过数据连接发送的响应,但传输的行的格式相同):http:// hg .python.org / CPython的/文件/ 8af2dc11464f /库/ ftplib.py#l577

#4


The examples attached to ghostdog74's answer have a bit of a bug: the list you get back is the whole line of the response, so you get something like

ghostdog74的答案附带的例子有一点错误:你得到的列表是响应的整行,所以你得到类似的东西

drwxrwxrwx    4 5063     5063         4096 Sep 13 20:00 resized

This means if your directory name is something like '50' (which is was in my case), you'll get a false positive. I modified the code to handle this:

这意味着如果您的目录名称类似于'50'(在我的情况下),您将得到误报。我修改了代码来处理这个:

def directory_exists_here(self, directory_name):
    filelist = []
    self.ftp.retrlines('LIST',filelist.append)
    for f in filelist:
        if f.split()[-1] == directory_name:
            return True
    return False

N.B., this is inside an FTP wrapper class I wrote and self.ftp is the actual FTP connection.

N.B.,这是我写的FTP包装器类,self.ftp是实际的FTP连接。

#5


Tom is correct, but no one voted him up however for the satisfaction who voted up ghostdog74 I will mix and write this code, works for me, should work for you guys.

汤姆是正确的,但没有人投票给他,但是为了满足谁投票了ghostdog74我会混合编写这段代码,对我有用,应该适合你们。

import ftplib
server="localhost"
user="user"
uploadToDir="public_html"
password="test@email.com"
try:
    ftp = ftplib.FTP(server)    
    ftp.login(user,password)
except Exception,e:
    print e
else:    
    filelist = [] #to store all files
    ftp.retrlines('NLST',filelist.append)    # append to list  
    num=0
    for f in filelist:
        if f.split()[-1] == uploadToDir:
            #do something
            num=1
    if num==0:
        print "No public_html"
        #do your processing here

first of all if you follow ghost dog method, even if you say directory "public" in f, even when it doesnt exist it will evaluate to true because the word public exist in "public_html" so thats where Tom if condition can be used so I changed it to if f.split()[-1] == uploadToDir:.

首先,如果你遵循鬼狗方法,即使你在f中说目录“公共”,即使它不存在它也会评估为真,因为公共单词public存在于“public_html”中,所以那就是汤姆如果条件可以使用所以如果f.split()[ - 1] == uploadToDir:我将其更改为:

Also if you enter a directory name somethig that doesnt exist but some files and folder exist the second by ghostdog74 will never execute because its never 0 as overridden by f in for loop so I used num variable instead of f and voila the goodness follows...

另外,如果你输入的目录名称somethig不存在,但存在一些文件和文件夹,第二个由ghostdog74永远不会执行,因为它永远不会被f for for循环覆盖,所以我使用num变量而不是f而且好了以下... 。

Vinay and Jonathon are right about what they commented.

Vinay和Jonathon对他们评论的内容是正确的。

#6


In 3.x nlst() method is deprecated. Use this code:

在3.x中,nlst()方法已弃用。使用此代码:

import ftplib

remote = ftplib.FTP('example.com')
remote.login()

if 'foo' in [name for name, data in list(remote.mlsd())]:
    # do your stuff

The list() call is needed because mlsd() returns a generator and they do not support checking what is in them (do not have __contains__() method).

需要list()调用,因为mlsd()返回一个生成器,并且它们不支持检查其中的内容(没有__contains __()方法)。

You can wrap [name for name, data in list(remote.mlsd())] list comp in a function of method and call it when you will need to just check if a directory (or file) exists.

您可以在方法的函数中包装[名称,列表中的数据(remote.mlsd())] list comp,并在需要检查目录(或文件)是否存在时调用它。

#7


=> I found this web-page while googling for a way to check if a file exists using ftplib in python. The following is what I figured out (hope it helps someone):

=>我在google搜索这个网页的同时检查文件是否存在使用python中的ftplib。以下是我想到的(希望它可以帮助某人):

=> When trying to list non-existent files/directories, ftplib raises an exception. Even though Adding a try/except block is a standard practice and a good idea, I would prefer my FTP scripts to download file(s) only after making sure they exist. This helps in keeping my scripts simpler - at least when listing a directory on the FTP server is possible.

=>当尝试列出不存在的文件/目录时,ftplib会引发异常。即使添加一个try / except块是一个标准的做法和一个好主意,我希望我的FTP脚本只有在确定它们存在后才能下载文件。这有助于保持我的脚本更简单 - 至少在FTP服务器上列出目录是可能的。

For example, the Edgar FTP server has multiple files that are stored under the directory /edgar/daily-index/. Each file is named liked "master.YYYYMMDD.idx". There is no guarantee that a file will exist for every date (YYYYMMDD) - there is no file dated 24th Nov 2013, but there is a file dated: 22th Nov 2013. How does listing work in these two cases?

例如,Edgar FTP服务器有多个文件存储在/ edgar / daily-index /目录下。每个文件都被命名为“master.YYYYMMDD.idx”。无法保证每个日期都存在一个文件(YYYYMMDD) - 没有日期为2013年11月24日的文件,但有一个日期为2013年11月22日的文件。这两种情况下的列表如何工作?

# Code
from __future__ import print_function  
import ftplib  

ftp_client = ftplib.FTP("ftp.sec.gov", "anonymous", "MY.EMAIL@gmail.com")  
resp = ftp_client.sendcmd("MLST /edgar/daily-index/master.20131122.idx")  
print(resp)   
resp = ftp_client.sendcmd("MLST /edgar/daily-index/master.20131124.idx")  
print(resp)  

# Output
250-Start of list for /edgar/daily-index/master.20131122.idx  
modify=20131123030124;perm=adfr;size=301580;type=file;unique=11UAEAA398;  
UNIX.group=1;UNIX.mode=0644;UNIX.owner=1019;  
/edgar/daily-index/master.20131122.idx
250 End of list  

Traceback (most recent call last):
File "", line 10, in <module>
resp = ftp_client.sendcmd("MLST /edgar/daily-index/master.20131124.idx")
File "lib/python2.7/ftplib.py", line 244, in sendcmd
return self.getresp()
File "lib/python2.7/ftplib.py", line 219, in getresp
raise error_perm, resp
ftplib.error_perm: 550 '/edgar/daily-index/master.20131124.idx' cannot be listed

As expected, listing a non-existent file generates an exception.

正如所料,列出不存在的文件会生成异常。

=> Since I know that the Edgar FTP server will surely have the directory /edgar/daily-index/, my script can do the following to avoid raising exceptions due to non-existent files:
a) list this directory.
b) download the required file(s) if they are are present in this listing - To check the listing I typically perform a regexp search, on the list of strings that the listing operation returns.

=>因为我知道Edgar FTP服务器肯定会有目录/ edgar / daily-index /,我的脚本可以执行以下操作以避免因文件不存在而引发异常:a)列出此目录。 b)下载所需文件(如果它们存在于此列表中) - 要检查列表,我通常在列表操作返回的字符串列表上执行正则表达式搜索。

For example this script tries to download files for the past three days. If a file is found for a certain date then it is downloaded, else nothing happens.

例如,此脚本会尝试下载过去三天的文件。如果找到某个日期的文件,则下载该文件,否则没有任何反应。

import ftplib
import re
from datetime import date, timedelta

ftp_client = ftplib.FTP("ftp.sec.gov", "anonymous", "MY.EMAIL@gmail.com")
listing = []
# List the directory and store each directory entry as a string in an array
ftp_client.retrlines("LIST /edgar/daily-index", listing.append)
# go back 1,2 and 3 days
for diff in [1,2,3]:
  today = (date.today() - timedelta(days=diff)).strftime("%Y%m%d")
  month = (date.today() - timedelta(days=diff)).strftime("%Y_%m")
  # the absolute path of the file we want to download - if it indeed exists
  file_path = "/edgar/daily-index/master.%(date)s.idx" % { "date": today }
  # create a regex to match the file's name
  pattern = re.compile("master.%(date)s.idx" % { "date": today })
  # filter out elements from the listing that match the pattern
  found = filter(lambda x: re.search(pattern, x) != None, listing)
  if( len(found) > 0 ):
    ftp_client.retrbinary(
      "RETR %(file_path)s" % { "file_path": file_path },
      open(
        './edgar/daily-index/%(month)s/master.%(date)s.idx' % {
          "date": today
        }, 'wb'
      ).write
    )

=> Interestingly, there are situations where we cannot list a directory on the FTP server. The edgar FTP server, for example, disallows listing on /edgar/data because it contains far too many sub-directories. In such cases, I wouldn't be able to use the "List and check for existence" approach described here - in these cases I would have to use exception handling in my downloader script to recover from non-existent file/directory access attempts.

=>有趣的是,有些情况下我们无法在FTP服务器上列出目录。例如,edgar FTP服务器不允许在/ edgar / data上列出,因为它包含太多的子目录。在这种情况下,我将无法使用此处描述的“列表和检查存在”方法 - 在这些情况下,我将不得不在我的下载程序脚本中使用异常处理来从不存在的文件/目录访问尝试中恢复。

#1


Nslt will list an array for all files in ftp server. Just check if your folder name is there.

Nslt将为ftp服务器中的所有文件列出一个数组。只需检查您的文件夹名称是否存在。

from ftplib import FTP 
ftp = FTP('yourserver')
ftp.login('username', 'password')

folderName = 'yourFolderName'
if folderName in ftp.nlst():
    #do needed task 

#2


you can use a list. example

你可以使用一个清单。例

import ftplib
server="localhost"
user="user"
password="test@email.com"
try:
    ftp = ftplib.FTP(server)    
    ftp.login(user,password)
except Exception,e:
    print e
else:    
    filelist = [] #to store all files
    ftp.retrlines('LIST',filelist.append)    # append to list  
    f=0
    for f in filelist:
        if "public_html" in f:
            #do something
            f=1
    if f==0:
        print "No public_html"
        #do your processing here

#3


You can send "MLST path" over the control connection. That will return a line including the type of the path (notice 'type=dir' down here):

您可以通过控制连接发送“MLST路径”。这将返回一行,包括路径的类型(注意'type = dir'在这里):

250-Listing "/home/user":
 modify=20131113091701;perm=el;size=4096;type=dir;unique=813gc0004; /
250 End MLST.

Translated into python that should be something along these lines:

转换成python应该是这些方面的东西:

import ftplib
ftp = ftplib.FTP()
ftp.connect('ftp.somedomain.com', 21)
ftp.login()
resp = ftp.sendcmd('MLST pathname')
if 'type=dir;' in resp:
    # it should be a directory
    pass

Of course the code above is not 100% reliable and would need a 'real' parser. You can look at the implementation of MLSD command in ftplib.py which is very similar (MLSD differs from MLST in that the response in sent over the data connection but the format of the lines being transmitted is the same): http://hg.python.org/cpython/file/8af2dc11464f/Lib/ftplib.py#l577

当然,上面的代码不是100%可靠,需要一个“真正的”解析器。您可以在ftplib.py中查看MLSD命令的实现,它非常相似(MLSD与MLST的不同之处在于通过数据连接发送的响应,但传输的行的格式相同):http:// hg .python.org / CPython的/文件/ 8af2dc11464f /库/ ftplib.py#l577

#4


The examples attached to ghostdog74's answer have a bit of a bug: the list you get back is the whole line of the response, so you get something like

ghostdog74的答案附带的例子有一点错误:你得到的列表是响应的整行,所以你得到类似的东西

drwxrwxrwx    4 5063     5063         4096 Sep 13 20:00 resized

This means if your directory name is something like '50' (which is was in my case), you'll get a false positive. I modified the code to handle this:

这意味着如果您的目录名称类似于'50'(在我的情况下),您将得到误报。我修改了代码来处理这个:

def directory_exists_here(self, directory_name):
    filelist = []
    self.ftp.retrlines('LIST',filelist.append)
    for f in filelist:
        if f.split()[-1] == directory_name:
            return True
    return False

N.B., this is inside an FTP wrapper class I wrote and self.ftp is the actual FTP connection.

N.B.,这是我写的FTP包装器类,self.ftp是实际的FTP连接。

#5


Tom is correct, but no one voted him up however for the satisfaction who voted up ghostdog74 I will mix and write this code, works for me, should work for you guys.

汤姆是正确的,但没有人投票给他,但是为了满足谁投票了ghostdog74我会混合编写这段代码,对我有用,应该适合你们。

import ftplib
server="localhost"
user="user"
uploadToDir="public_html"
password="test@email.com"
try:
    ftp = ftplib.FTP(server)    
    ftp.login(user,password)
except Exception,e:
    print e
else:    
    filelist = [] #to store all files
    ftp.retrlines('NLST',filelist.append)    # append to list  
    num=0
    for f in filelist:
        if f.split()[-1] == uploadToDir:
            #do something
            num=1
    if num==0:
        print "No public_html"
        #do your processing here

first of all if you follow ghost dog method, even if you say directory "public" in f, even when it doesnt exist it will evaluate to true because the word public exist in "public_html" so thats where Tom if condition can be used so I changed it to if f.split()[-1] == uploadToDir:.

首先,如果你遵循鬼狗方法,即使你在f中说目录“公共”,即使它不存在它也会评估为真,因为公共单词public存在于“public_html”中,所以那就是汤姆如果条件可以使用所以如果f.split()[ - 1] == uploadToDir:我将其更改为:

Also if you enter a directory name somethig that doesnt exist but some files and folder exist the second by ghostdog74 will never execute because its never 0 as overridden by f in for loop so I used num variable instead of f and voila the goodness follows...

另外,如果你输入的目录名称somethig不存在,但存在一些文件和文件夹,第二个由ghostdog74永远不会执行,因为它永远不会被f for for循环覆盖,所以我使用num变量而不是f而且好了以下... 。

Vinay and Jonathon are right about what they commented.

Vinay和Jonathon对他们评论的内容是正确的。

#6


In 3.x nlst() method is deprecated. Use this code:

在3.x中,nlst()方法已弃用。使用此代码:

import ftplib

remote = ftplib.FTP('example.com')
remote.login()

if 'foo' in [name for name, data in list(remote.mlsd())]:
    # do your stuff

The list() call is needed because mlsd() returns a generator and they do not support checking what is in them (do not have __contains__() method).

需要list()调用,因为mlsd()返回一个生成器,并且它们不支持检查其中的内容(没有__contains __()方法)。

You can wrap [name for name, data in list(remote.mlsd())] list comp in a function of method and call it when you will need to just check if a directory (or file) exists.

您可以在方法的函数中包装[名称,列表中的数据(remote.mlsd())] list comp,并在需要检查目录(或文件)是否存在时调用它。

#7


=> I found this web-page while googling for a way to check if a file exists using ftplib in python. The following is what I figured out (hope it helps someone):

=>我在google搜索这个网页的同时检查文件是否存在使用python中的ftplib。以下是我想到的(希望它可以帮助某人):

=> When trying to list non-existent files/directories, ftplib raises an exception. Even though Adding a try/except block is a standard practice and a good idea, I would prefer my FTP scripts to download file(s) only after making sure they exist. This helps in keeping my scripts simpler - at least when listing a directory on the FTP server is possible.

=>当尝试列出不存在的文件/目录时,ftplib会引发异常。即使添加一个try / except块是一个标准的做法和一个好主意,我希望我的FTP脚本只有在确定它们存在后才能下载文件。这有助于保持我的脚本更简单 - 至少在FTP服务器上列出目录是可能的。

For example, the Edgar FTP server has multiple files that are stored under the directory /edgar/daily-index/. Each file is named liked "master.YYYYMMDD.idx". There is no guarantee that a file will exist for every date (YYYYMMDD) - there is no file dated 24th Nov 2013, but there is a file dated: 22th Nov 2013. How does listing work in these two cases?

例如,Edgar FTP服务器有多个文件存储在/ edgar / daily-index /目录下。每个文件都被命名为“master.YYYYMMDD.idx”。无法保证每个日期都存在一个文件(YYYYMMDD) - 没有日期为2013年11月24日的文件,但有一个日期为2013年11月22日的文件。这两种情况下的列表如何工作?

# Code
from __future__ import print_function  
import ftplib  

ftp_client = ftplib.FTP("ftp.sec.gov", "anonymous", "MY.EMAIL@gmail.com")  
resp = ftp_client.sendcmd("MLST /edgar/daily-index/master.20131122.idx")  
print(resp)   
resp = ftp_client.sendcmd("MLST /edgar/daily-index/master.20131124.idx")  
print(resp)  

# Output
250-Start of list for /edgar/daily-index/master.20131122.idx  
modify=20131123030124;perm=adfr;size=301580;type=file;unique=11UAEAA398;  
UNIX.group=1;UNIX.mode=0644;UNIX.owner=1019;  
/edgar/daily-index/master.20131122.idx
250 End of list  

Traceback (most recent call last):
File "", line 10, in <module>
resp = ftp_client.sendcmd("MLST /edgar/daily-index/master.20131124.idx")
File "lib/python2.7/ftplib.py", line 244, in sendcmd
return self.getresp()
File "lib/python2.7/ftplib.py", line 219, in getresp
raise error_perm, resp
ftplib.error_perm: 550 '/edgar/daily-index/master.20131124.idx' cannot be listed

As expected, listing a non-existent file generates an exception.

正如所料,列出不存在的文件会生成异常。

=> Since I know that the Edgar FTP server will surely have the directory /edgar/daily-index/, my script can do the following to avoid raising exceptions due to non-existent files:
a) list this directory.
b) download the required file(s) if they are are present in this listing - To check the listing I typically perform a regexp search, on the list of strings that the listing operation returns.

=>因为我知道Edgar FTP服务器肯定会有目录/ edgar / daily-index /,我的脚本可以执行以下操作以避免因文件不存在而引发异常:a)列出此目录。 b)下载所需文件(如果它们存在于此列表中) - 要检查列表,我通常在列表操作返回的字符串列表上执行正则表达式搜索。

For example this script tries to download files for the past three days. If a file is found for a certain date then it is downloaded, else nothing happens.

例如,此脚本会尝试下载过去三天的文件。如果找到某个日期的文件,则下载该文件,否则没有任何反应。

import ftplib
import re
from datetime import date, timedelta

ftp_client = ftplib.FTP("ftp.sec.gov", "anonymous", "MY.EMAIL@gmail.com")
listing = []
# List the directory and store each directory entry as a string in an array
ftp_client.retrlines("LIST /edgar/daily-index", listing.append)
# go back 1,2 and 3 days
for diff in [1,2,3]:
  today = (date.today() - timedelta(days=diff)).strftime("%Y%m%d")
  month = (date.today() - timedelta(days=diff)).strftime("%Y_%m")
  # the absolute path of the file we want to download - if it indeed exists
  file_path = "/edgar/daily-index/master.%(date)s.idx" % { "date": today }
  # create a regex to match the file's name
  pattern = re.compile("master.%(date)s.idx" % { "date": today })
  # filter out elements from the listing that match the pattern
  found = filter(lambda x: re.search(pattern, x) != None, listing)
  if( len(found) > 0 ):
    ftp_client.retrbinary(
      "RETR %(file_path)s" % { "file_path": file_path },
      open(
        './edgar/daily-index/%(month)s/master.%(date)s.idx' % {
          "date": today
        }, 'wb'
      ).write
    )

=> Interestingly, there are situations where we cannot list a directory on the FTP server. The edgar FTP server, for example, disallows listing on /edgar/data because it contains far too many sub-directories. In such cases, I wouldn't be able to use the "List and check for existence" approach described here - in these cases I would have to use exception handling in my downloader script to recover from non-existent file/directory access attempts.

=>有趣的是,有些情况下我们无法在FTP服务器上列出目录。例如,edgar FTP服务器不允许在/ edgar / data上列出,因为它包含太多的子目录。在这种情况下,我将无法使用此处描述的“列表和检查存在”方法 - 在这些情况下,我将不得不在我的下载程序脚本中使用异常处理来从不存在的文件/目录访问尝试中恢复。