5

I would like to list all directories on a ftp directory and then enter each of them. The problem is that my code also list file and try to enter them as well.

  1. Is there a way to get a return value from the method ftp.cwd ?
  2. Is there a way to get only directory name in the first place, or there is a better way to do what I want.

Here is the code I am using now:

    from ftplib import FTP
    ftp = FTP('ftp.overtherainbow.com')
    ftp.login()
    for name in ftp.nlst():
        print "listing: " + name
        ftp.cwd(name)
        ftp.retrlines('LIST')
        ftp.cwd('../')
yossi
  • 12,945
  • 28
  • 84
  • 110

4 Answers4

6

The FTP protocol doesn't have a way of distinguishing between directories and files (as for listing). I think the best bet would be either, try and fail

try:
    ftp.cwd(name)
except ftplib.error_perm as detail:
    print("It's probably not a directory:", detail)

Or otherwise you may want to parse the output from the directory listing. This will not be platform independent though, because directory listings differ from OS to OS. As shown here...

Community
  • 1
  • 1
Uku Loskit
  • 40,868
  • 9
  • 92
  • 93
2

Here is a Python 3.3 solution (mlsd): http://docs.python.org/3/library/ftplib.html#ftplib.FTP.mlsd

ftp.nlst and ftp.dir are "Deprecated since version 3.3: use mlsd() instead."

tommy.carstensen
  • 8,962
  • 15
  • 65
  • 108
  • 1
    It is not a matter of the Python version one is using, `nlst` is very much alive. `mlsd` can be used _when the FTP server supports_ [RFC 3659](https://tools.ietf.org/html/rfc3659.html); not the case for many servers out there. – Brandt Apr 23 '20 at 12:01
1

This is a bit ugly, but the ftplib seems not very easy to use.

>>> x=[]
>>> ftp.dir('-d','*/',lambda L:x.append(L.split()[-1]))
>>> x
['access-logs/', 'etc/', 'mail/', 'perl/', 'proxy/', 'public_ftp/', 'public_html/', 'subversion/', 'tmp/', 'web/', 'www/']
Kabie
  • 10,489
  • 1
  • 38
  • 45
0

That worked for me:

def get_current_dir_subdirs(self):
    ret = []
    self.ftp.dir("",ret.append)
    ret = [x.split()[-1] for x in ret if x.startswith("d")]
    return ret 
Guy L
  • 2,824
  • 2
  • 27
  • 37