Comment analyser une liste de fichiers pour obtenir uniquement les noms de fichiers en Python?

StackOverflow https://stackoverflow.com/questions/237699

Question

Disons que j'utilise le ftplib de Python pour récupérer une liste de fichiers journaux d’un serveur FTP. Comment pourrais-je analyser cette liste de fichiers pour obtenir uniquement les noms de fichiers (la dernière colonne) dans une liste? Voir le lien ci-dessus pour un exemple de sortie.

Était-ce utile?

La solution

Utiliser retrlines () n’est probablement pas la meilleure idée dans ce cas-ci, puisqu’il n’imprime que sur la console. Vous devrez donc faire des choses difficiles pour atteindre même cette sortie. Un meilleur choix serait probablement d’utiliser la méthode nlst (), qui retourne exactement ce que vous voulez: une liste des noms de fichiers.

Autres conseils

Cette meilleure réponse

Vous pouvez utiliser ftp.nlst () au lieu de ftp.retrlines () . Cela vous donnera exactement ce que vous voulez.

Si vous ne le pouvez pas, lisez ce qui suit:

Générateurs pour les processus sysadmin

Dans son article désormais célèbre, Trucs de générateur pour les programmeurs de systèmes: introduction , David M. Beazley donne beaucoup de recettes pour répondre à ce type de problème de données avec du code wuick et réutilisable.

E.G:

# empty list that will receive all the log entry
log = [] 
# we pass a callback function bypass the print_line that would be called by retrlines
# we do that only because we cannot use something better than retrlines
ftp.retrlines('LIST', callback=log.append)
# we use rsplit because it more efficient in our case if we have a big file
files = (line.rsplit(None, 1)[1] for line in log)
# get you file list
files_list = list(files)

Pourquoi ne générons-nous pas immédiatement la liste?

Eh bien, c’est parce que cela vous offre beaucoup de souplesse: vous pouvez appliquer n’importe quel générateur intermédiaire pour filtrer les fichiers avant de le transformer en liste_fichiers : c’est comme un tuyau, ajoutez une ligne, vous ajoutez un processus sans surchauffe (puisqu'il s'agit de générateurs). Et si vous vous débarrassez de retrlines , cela fonctionne quand même, c’est encore mieux car vous ne stockez pas la liste, même une fois.

EDIT: eh bien, j'ai lu le commentaire à l'autre réponse et il est dit que cela ne fonctionnera pas s'il y a de la place dans le nom.

Cool, cela illustrera pourquoi cette méthode est pratique. Si vous souhaitez modifier quelque chose dans le processus, il vous suffit de modifier une ligne. Échange:

files = (line.rsplit(None, 1)[1] for line in log)

et

# join split the line, get all the item from the field 8 then join them
files = (' '.join(line.split()[8:]) for line in log)

Ok, cela n’est peut-être pas évident ici, mais pour les scripts de traitement par lots énormes, c’est bien: -)

Et une méthode légèrement moins optimale, en passant, si vous êtes bloqué avec retrlines () pour une raison quelconque, consiste à passer une fonction en tant que second argument de retrlines (); il sera appelé pour chaque élément de la liste. Donc, quelque chose comme ceci (en supposant que vous ayez un objet FTP nommé 'ftp') fonctionnerait également:

filenames = []
ftp.retrlines('LIST', lambda line: filenames.append(line.split()[-1]))

La liste 'noms de fichiers' sera alors une liste des noms de fichiers.

Existe-t-il une quelconque raison pour laquelle ftplib.FTP.nlst () ne fonctionne pas pour vous? Je viens de vérifier et il ne renvoie que les noms des fichiers d'un répertoire donné.

Étant donné que chaque nom de fichier de la sortie commence par la même colonne, il vous suffit d'obtenir la position du point sur la première ligne:

  

drwxrwsr-x 5 ftp-usr pdmaint 1536 20 mars 09:48.

Découpez ensuite le nom de fichier des autres lignes en utilisant la position de ce point comme index de départ.

Le point étant le dernier caractère de la ligne, vous pouvez utiliser la longueur de la ligne moins 1 comme index. Donc, le code final ressemble à ceci:

lines = ftp.retrlines('LIST')
lines = lines.split("\n") # This should split the string into an array of lines

filename_index = len(lines[0]) - 1
files = []

for line in lines:
    files.append(line[filename_index:])

Si le serveur FTP prend en charge la commande MLSD , reportez-vous à la section intitulée «Cas d'un seul répertoire» de que réponse.

Utilisez une instance (disons ftpd ) de la classe FTPDirectory , appelez sa méthode .getdata avec connecté ftplib.FTP instance dans le bon dossier, vous pouvez alors:

directory_filenames= [ftpfile.name for ftpfile in ftpd.files]

Je crois que cela devrait fonctionner pour vous.

file_name_list = [' '.join(each_file.split()).split()[-1] for each_file_detail in file_list_from_log]

NOTES -

  1. Je suppose ici que vous souhaitez que les données du programme (sous forme de liste), pas sur la console.

  2. each_file_detail est chaque ligne produite par le programme.

  3. '' .join (each_file.split ())

Pour remplacer plusieurs espaces par un espace.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top