Domanda

Quindi diciamo che sto usando ftplib per recuperare un elenco di file di registro da un server FTP. Come analizzerei quell'elenco di file per ottenere solo i nomi dei file (l'ultima colonna) all'interno di un elenco? Vedi il link sopra per esempio output.

È stato utile?

Soluzione

L'uso di retrlines () probabilmente non è la migliore idea lì, dal momento che stampa solo sulla console e quindi dovresti fare cose difficili anche per ottenere quell'output. Una scommessa probabilmente migliore sarebbe quella di utilizzare il metodo nlst (), che restituisce esattamente quello che vuoi: un elenco dei nomi dei file.

Altri suggerimenti

Questa migliore risposta

Puoi usare ftp.nlst () invece di ftp.retrlines () . Ti darà esattamente quello che vuoi.

Se non puoi, leggi quanto segue:

Generatori per processi sysadmin

Nella sua ormai famosa recensione, Trucchi per generatori per programmatori di sistemi Un'introduzione , David M. Beazley fornisce molte ricevute per rispondere a questo tipo di problema relativo ai dati con wuick e codice riutilizzabile.

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)

Perché non generiamo immediatamente l'elenco?

Bene, perché farlo in questo modo ti offre molta flessibilità: puoi applicare qualsiasi generatore intermedio per filtrare i file prima di trasformarlo in files_list : è proprio come pipe, aggiungi una linea, aggiungi un processo senza surriscaldamento (poiché è generatori). E se ti sbarazzi di retrlines , funziona ancora perché è ancora meglio perché non memorizzi l'elenco nemmeno una volta.

EDIT: bene, ho letto il commento all'altra risposta e dice che questo non funzionerà se c'è spazio nel nome.

Bene, questo illustrerà perché questo metodo è utile. Se vuoi cambiare qualcosa nel processo, devi solo cambiare una linea. Scambia:

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

e

# 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, qui potrebbe non essere ovvio, ma per gli script di processo batch enormi, è bello :-)

E un metodo leggermente meno ottimale, comunque, se sei bloccato usando retrlines () per qualche motivo, è passare una funzione come secondo argomento a retrlines (); verrà chiamato per ogni elemento nell'elenco. Quindi qualcosa del genere (supponendo che tu abbia un oggetto FTP chiamato 'ftp') funzionerebbe anche:

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

L'elenco 'nomi file' sarà quindi un elenco dei nomi dei file.

C'è qualche motivo per cui ftplib.FTP.nlst () non funziona per te? Ho appena controllato e restituisce solo i nomi dei file in una determinata directory.

Poiché ogni nome di file nell'output inizia nella stessa colonna, tutto ciò che devi fare è ottenere la posizione del punto sulla prima riga:

  

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

Quindi tagliare il nome del file dalle altre righe usando la posizione di quel punto come indice iniziale.

Dato che il punto è l'ultimo carattere sulla linea, puoi usare la lunghezza della linea meno 1 come indice. Quindi il codice finale è qualcosa del genere:

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:])

Se il server FTP supporta il comando MLSD , consultare la sezione "caso di directory singola" da che rispondi.

Utilizza un'istanza (ad esempio ftpd ) della classe FTPDirectory , chiama il suo metodo .getdata con ftplib.FTP istanza nella cartella corretta, quindi puoi:

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

Credo che dovrebbe funzionare per te.

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

NOTE -

  1. Qui sto assumendo che tu voglia i dati nel programma (come elenco), non sulla console.

  2. each_file_detail è ogni riga prodotta dal programma.

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

Per sostituire più spazi con 1 spazio.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top