2008-09-21 18 views
44

Vous pouvez utiliser ftplib pour une prise en charge FTP complète en Python. Cependant, le meilleur moyen d'obtenir une liste de répertoires est:Utilisation de ftplib de Python pour obtenir une liste de répertoires, portabled

# 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 

qui donne:

$ 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 
... 

Je pense que l'idée est d'analyser les résultats pour obtenir la liste des répertoires. Cependant, cette liste dépend directement du formatage de la liste par le serveur FTP. Il serait très compliqué d'écrire du code pour avoir à anticiper toutes les différentes manières dont les serveurs FTP pourraient formater cette liste.

Existe-t-il un moyen portable d'obtenir un tableau rempli avec la liste de répertoires?

(le tableau ne devrait avoir les noms de dossier.)

Répondre

94

Essayez d'utiliser ftp.nlst(dir).

Cependant, notez que si le dossier est vide, il peut lancer une erreur:

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 
+2

Oh, joliment repéré sur le 550! Upvoted. :) –

+3

oui, cela répond à la question, et je pense que c'est génial mais ce n'est pas une réponse extensible. Et si j'ai besoin d'un objet fichier avec des propriétés? ne pas être pessimiste, mais ce serait pratique. –

+10

Merci pour votre aide. 5 ans plus tard: obsolète depuis la version 3.3: utilisez plutôt mlsd(). –

2

Il n'y a pas standard pour la mise en page de la réponse LIST. Vous devez écrire du code pour gérer les mises en page les plus populaires. Je commencerais avec les formats Linux ls et Windows Server DIR. Cependant, il y a beaucoup de variété.

Revient à la méthode nlst (en retournant le résultat de la commande NLST) si vous ne pouvez pas analyser la liste la plus longue. Pour les points bonus, trichez: peut-être que le plus long numéro de la ligne contenant un nom de fichier connu est sa longueur.

+8

Vous ne devriez jamais supposer cela. Deviner conduit toujours à des bogues abscurs quand on s'y attend le moins – iElectric

+0

Tout à fait vrai, d'où mes nombreux tests unitaires et tests d'intégration. :) S'ils ont besoin de la longueur, cependant, c'est soit: j'espère que le format correspond à l'un de ceux qu'ils ont testé; Pause; ou essayez de comprendre où trouver la longueur. Aucune des options n'est idéale. –

24

La manière fiable et normalisée d'analyser la liste des répertoires FTP consiste à utiliser la commande MLSD, qui devrait désormais être prise en charge par tous les serveurs FTP récents/décents.

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

Le code ci-dessus imprimera:

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 
... 

A partir de python 3.3, ftplib fournira une méthode spécifique pour ce faire:

0

Je suis coincé avec un serveur FTP (serveur virtuel Rackspace Cloud Sites) qui ne semble pas supporter le MLSD. Pourtant j'ai besoin de plusieurs champs d'information de fichier, tels que la taille et l'horodatage, pas seulement le nom de fichier, donc je dois utiliser la commande DIR. Sur ce serveur, la sortie de DIR ressemble beaucoup à celle des OP. Au cas où cela aiderait quelqu'un, voici une petite classe Python qui analyse une ligne de cette sortie pour obtenir le nom du fichier, la taille et l'horodatage.

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') 

Pas très portable, je sais, mais facile d'étendre ou de modifier pour traiter différents serveurs FTP différents.

0

C'est de docs Python

>>> 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

Cela m'a aidé avec mon code.

Lorsque j'ai essayé de fusionner uniquement un type de fichiers et de les afficher à l'écran en ajoutant une condition qui teste chaque ligne.

Vous aimez cette

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) 
-1

J'ai trouvé mon chemin ici, tout en essayant d'obtenir les noms de fichiers, derniers timbres modifiés, la taille des fichiers, etc et je voulais ajouter mon code. Il n'a fallu que quelques minutes pour écrire une boucle afin d'analyser le ftp.dir(dir_list.append) en utilisant python std lib comme strip() (pour nettoyer la ligne de texte) et split() pour créer un tableau.

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']