webentwicklung-frage-antwort-db.com.de

Verwenden von Pythons ftplib, um portabel eine Verzeichnisliste zu erhalten

Sie können ftplib für die vollständige FTP-Unterstützung in Python verwenden. Die bevorzugte Methode zum Abrufen einer Verzeichnisliste ist jedoch:

# File: ftplib-example-1.py

import ftplib

ftp = ftplib.FTP("www.python.org")
ftp.login("anonymous", "ftplib-example-1")

data = []

ftp.dir(data.append)

ftp.quit()

for line in data:
    print "-", line

Welche Erträge:

$ python ftplib-example-1.py
- total 34
- drwxrwxr-x  11 root     4127         512 Sep 14 14:18 .
- drwxrwxr-x  11 root     4127         512 Sep 14 14:18 ..
- drwxrwxr-x   2 root     4127         512 Sep 13 15:18 RCS
- lrwxrwxrwx   1 root     bin           11 Jun 29 14:34 README -> welcome.msg
- drwxr-xr-x   3 root     wheel        512 May 19  1998 bin
- drwxr-sr-x   3 root     1400         512 Jun  9  1997 dev
- drwxrwxr--   2 root     4127         512 Feb  8  1998 dup
- drwxr-xr-x   3 root     wheel        512 May 19  1998 etc
...

Ich denke, die Idee ist, die Ergebnisse zu analysieren, um die Verzeichnisliste zu erhalten. Diese Auflistung hängt jedoch direkt von der Formatierung der Liste durch den FTP-Server ab. Es wäre sehr umständlich, Code dafür zu schreiben, wenn man all die unterschiedlichen Arten vorwegnehmen müsste, wie FTP-Server diese Liste formatieren könnten.

Gibt es eine tragbare Möglichkeit, ein Array mit der Verzeichnisliste zu füllen?

(Das Array sollte nur die Ordnernamen enthalten.)

53
andrewrk

Versuchen Sie, ftp.nlst(dir) zu verwenden.

Beachten Sie jedoch, dass ein leerer Ordner möglicherweise einen Fehler auslöst:

files = []

try:
    files = ftp.nlst()
except ftplib.error_perm, resp:
    if str(resp) == "550 No files found":
        print "No files in this directory"
    else:
        raise

for f in files:
    print f
114
William Keller

Die zuverlässige/standardisierte Methode zum Parsen der FTP-Verzeichnisliste ist die Verwendung des MLSD-Befehls, der jetzt von allen aktuellen/anständigen FTP-Servern unterstützt werden sollte.

import ftplib
f = ftplib.FTP()
f.connect("localhost")
f.login()
ls = []
f.retrlines('MLSD', ls.append)
for entry in ls:
    print entry

Der obige Code wird gedruckt:

modify=20110723201710;perm=el;size=4096;type=dir;unique=807g4e5a5; tests
modify=20111206092323;perm=el;size=4096;type=dir;unique=807g1008e0; .xchat2
modify=20111022125631;perm=el;size=4096;type=dir;unique=807g10001a; .gconfd
modify=20110808185618;perm=el;size=4096;type=dir;unique=807g160f9a; .skychart
...

Ausgehend von python 3.3 bietet ftplib eine spezielle Methode, um dies zu tun:

25

Ich habe mich hier zurechtgefunden, als ich nach Dateinamen, zuletzt geänderten Stempeln, Dateigrößen usw. gesucht habe, und wollte meinen Code hinzufügen. Es dauerte nur ein paar Minuten, um eine Schleife zu schreiben, in der das ftp.dir(dir_list.append) -Parsen mithilfe von python Standardbibliotheken wie strip() (zum Aufräumen der Textzeile) und split() ausgeführt wurde. um ein Array zu erstellen.

ftp = FTP('sick.domain.bro')
ftp.login()
ftp.cwd('path/to/data')

dir_list = []
ftp.dir(dir_list.append)

# main thing is identifing which char marks start of good stuff
# '-rw-r--r--   1 ppsrt    ppsrt      545498 Jul 23 12:07 FILENAME.FOO
#                               ^  (that is line[29])

for line in dir_list:
   print line[29:].strip().split(' ') # got yerself an array there bud!
   # EX ['545498', 'Jul', '23', '12:07', 'FILENAME.FOO']
3
chill_turner

Es gibt keinen Standard für das Layout der Antwort LIST. Sie müssten Code schreiben, um die gängigsten Layouts zu verarbeiten. Ich würde mit den Formaten Linux ls und Windows Server DIR beginnen. Es gibt jedoch viel Abwechslung.

Greifen Sie auf die Methode nlst zurück (und geben Sie das Ergebnis des Befehls NLST zurück), wenn Sie die längere Liste nicht analysieren können. Um Bonuspunkte zu erhalten, schummeln Sie: Vielleicht ist die längste Zahl in der Zeile, die einen bekannten Dateinamen enthält, die Länge.

2
Garth Kidd

Ich habe zufällig einen FTP-Server (virtueller Rackspace Cloud Sites-Server), der MLSD anscheinend nicht unterstützt. Ich benötige jedoch mehrere Felder mit Dateiinformationen, z. B. Größe und Zeitstempel, nicht nur den Dateinamen. Daher muss ich den Befehl DIR verwenden. Auf diesem Server ähnelt die Ausgabe von DIR stark den OPs. Falls es jemandem hilft, hier ist eine kleine Python Klasse, die eine Zeile einer solchen Ausgabe analysiert, um den Dateinamen, die Größe und den Zeitstempel zu erhalten.

import datetime

class FtpDir:
    def parse_dir_line(self, line):
        words = line.split()
        self.filename = words[8]
        self.size = int(words[4])
        t = words[7].split(':')
        ts = words[5] + '-' + words[6] + '-' + datetime.datetime.now().strftime('%Y') + ' ' + t[0] + ':' + t[1]
        self.timestamp = datetime.datetime.strptime(ts, '%b-%d-%Y %H:%M')

Ich weiß, dass es nicht sehr portabel ist, aber einfach zu erweitern oder zu ändern, um mit verschiedenen FTP-Servern fertig zu werden.

1
Steve Saporta

Dies ist aus Python docs

>>> from ftplib import FTP_TLS
>>> ftps = FTP_TLS('ftp.python.org')
>>> ftps.login()           # login anonymously before securing control 
channel
>>> ftps.prot_p()          # switch to secure data connection
>>> ftps.retrlines('LIST') # list directory content securely
total 9
drwxr-xr-x   8 root     wheel        1024 Jan  3  1994 .
drwxr-xr-x   8 root     wheel        1024 Jan  3  1994 ..
drwxr-xr-x   2 root     wheel        1024 Jan  3  1994 bin
drwxr-xr-x   2 root     wheel        1024 Jan  3  1994 etc
d-wxrwxr-x   2 ftp      wheel        1024 Sep  5 13:43 incoming
drwxr-xr-x   2 root     wheel        1024 Nov 17  1993 lib
drwxr-xr-x   6 1094     wheel        1024 Sep 13 19:07 pub
drwxr-xr-x   3 root     wheel        1024 Jan  3  1994 usr
-rw-r--r--   1 root     root          312 Aug  1  1994 welcome.msg
0
Jeeva

Das hat mir bei meinem Code geholfen.

Als ich versuchte, nur eine Art von Dateien zu filtern und sie auf dem Bildschirm anzuzeigen, fügte ich eine Bedingung hinzu, die für jede Zeile getestet wurde.

So was

Elif command == 'ls':
    print("directory of ", ftp.pwd())
    data = []
    ftp.dir(data.append)

    for line in data:
        x = line.split(".")
        formats=["gz", "Zip", "rar", "tar", "bz2", "xz"]
        if x[-1] in formats:
            print ("-", line)
0
MTS