Pregunta

Así que digamos que estoy usando ftplib de Python para recuperar una lista de archivos de registro de un servidor FTP. ¿Cómo puedo analizar esa lista de archivos para obtener solo los nombres de archivo (la última columna) dentro de una lista? Vea el enlace de arriba para el ejemplo de salida.

¿Fue útil?

Solución

El uso de retrlines () probablemente no sea la mejor idea, ya que solo se imprime en la consola, por lo que tendrías que hacer cosas difíciles para obtener esa salida. Una mejor opción sería utilizar el método nlst (), que devuelve exactamente lo que desea: una lista de los nombres de los archivos.

Otros consejos

Esta mejor respuesta

Es posible que desee utilizar ftp.nlst () en lugar de ftp.retrlines () . Te dará exactamente lo que quieres.

Si no puedes, lee lo siguiente:

Generadores para procesos sysadmin

En su ahora famosa revisión, Trucos del generador para programadores de sistemas Una introducción , David M. Beazley ofrece muchas recetas para responder a este tipo de problema de datos con wuick y código reutilizable.

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)

¿Por qué no generamos inmediatamente la lista?

Bueno, es porque hacerlo de esta manera te ofrece mucha flexibilidad: puedes aplicar cualquier generador intermedio para filtrar archivos antes de convertirlo en files_list : es como una tubería, agregar una línea, agregar una Proceso sin sobrecalentamiento (ya que se trata de generadores). Y si te deshaces de retrlines , todavía funciona, es incluso mejor porque no guardas la lista ni una sola vez.

EDITAR: bueno, leí el comentario a la otra respuesta y dice que esto no funcionará si hay algún espacio en el nombre.

Genial, esto ilustrará por qué este método es útil. Si desea cambiar algo en el proceso, simplemente cambia una línea. Swap:

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

y

# 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, esto puede no ser obvio aquí, pero para los scripts de procesos por lotes enormes, es bueno :-)

Y un método ligeramente menos óptimo, por cierto, si estás atascado usando retrlines () por alguna razón, es pasar una función como segundo argumento a retrlines (); Se llamará para cada elemento de la lista. Así que algo como esto (suponiendo que tenga un objeto FTP llamado 'ftp') también funcionaría:

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

La lista 'nombres de archivo' será una lista de los nombres de los archivos.

¿Hay alguna razón por la que ftplib.FTP.nlst () no te funcione? Acabo de verificar y solo devuelve los nombres de los archivos en un directorio determinado.

Dado que cada nombre de archivo en la salida comienza en la misma columna, todo lo que tienes que hacer es obtener la posición del punto en la primera línea:

  

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

Luego, corte el nombre de archivo de las otras líneas utilizando la posición de ese punto como el índice de inicio.

Dado que el punto es el último carácter de la línea, puedes usar la longitud de la línea menos 1 como el índice. Así que el código final es algo como esto:

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 el servidor FTP admite el comando MLSD , consulte la sección & # 8220; caso de directorio único & # 8221; desde esa respuesta.

Use una instancia (digamos ftpd ) de la clase FTPDirectory , llame a su método .getdata con ftplib.FTP instancia en la carpeta correcta, entonces puede:

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

Creo que debería funcionar para ti.

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

NOTAS -

  1. Aquí supongo que desea que los datos estén en el programa (como lista), no en la consola.

  2. each_file_detail es cada línea producida por el programa.

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

Para reemplazar múltiples espacios por 1 espacio.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top