3

I'm having difficulty retrieving a list of directories on a remote FTP site. This answer does not work (I get no output, it appears to hang).

Here's the simplest implementation I can think of - it should just print out the full path of every directory it finds:

import ftplib

def ftp_walk(ftp):    
print 'Path:', ftp.pwd()
    dirs = ftp.nlst()
    for item in (path for path in dirs if path not in ('.', '..')):
        try:
            ftp.cwd(item)
            print 'Changed to', ftp.pwd()
            ftp_walk(ftp)
            ftp.cwd('..')
        except Exception, e:
            print item, e

ftp = ftplib.FTP('ftp.site.com')                                        
ftp.login('user', 'pass')
ftp.cwd('1')
ftp_walk(ftp)

My directory structure is:

1/
 1-1/
   1-2/
 1-2/
 1-3/
 1-4

However, it only outputs the following. It suggests that the working directory is changed once to a new subdirectory, but when ftp_walk() is called with the new cwd, it doesn't go any further:

> Path: 1/
> Changed to 1-1/
Community
  • 1
  • 1
cyrus
  • 1,338
  • 3
  • 17
  • 26
  • In which function does it hang? (you can add some print statements in your code to see where it happens) – thesamet Dec 30 '11 at 06:08
  • also, your code does not check if an entry is a directory before it tries to cwd into it. – thesamet Dec 30 '11 at 06:11
  • I did not know there was something called a `tuple comprehension`. What is that statement in line 4? – Lelouch Lamperouge Dec 30 '11 at 06:38
  • Eknath - good question; it was a mistake on my part. However, it produces the same output as a list comprehension. – cyrus Dec 30 '11 at 06:41
  • thesamet - is there an accurate, server-independent way of checking whether the paths in NSLT output are directories? – cyrus Dec 30 '11 at 06:44
  • @EknathIyer it's a `generator expression`, and it's totally legitimate. It doesn't produce a tuple, but instead an iterable that yields the items on demand. That said, it would probably be simpler and thus more Pythonic to just use `for path in dirs:` and then `if path in ('.', '..'): continue`, and then proceed as before. – Karl Knechtel Dec 30 '11 at 07:39
  • if the ftp server supports `MLSD` command then see [`FTPTree`](http://stackoverflow.com/a/3114477/4279). – jfs Dec 30 '11 at 11:47
  • @KarlKnechtel, never knew that. Thank you – Lelouch Lamperouge Dec 30 '11 at 18:57
  • does it hang when there are more than 10 subdirs in a dir? – Rafael Oct 05 '17 at 13:20

2 Answers2

0

Before ftp.login('user', 'pass') and after the constructor, you need to call ftp.connect().

tbc0
  • 1,563
  • 1
  • 17
  • 21
0

Well I suppose the user you are logging in has access to all that structure, because otherwise it will return an error and won't list that specific directory.

If you're getting an exception, please put it here. Maybe you should try..finally your cwd so that it won't get lost. Can I suggest:

    try:
        ftp.cwd(item)
        print 'Changed to', ftp.pwd()
        try:
            ftp_walk(ftp)
        finally:
            ftp.cwd('..')
    except ftplib.error_perm, e:
        print item, e
augustomen
  • 8,977
  • 3
  • 43
  • 63
  • Thanks for the suggestion. I made your change, but it still hangs in the same place. I've made some slight changes to the directories on the FTP and it appears as though it only hangs on directories that do not subdirs. I'm not sure what that means, if anything. – cyrus Jan 04 '12 at 10:11
  • I have recently had that hanging problem, and couldn't figure out what was causing it, except maybe network privileges (firewall, etc). Anyway, switching on/off passive mode worked as a workaround. – augustomen Sep 28 '12 at 19:14