Si esto es sólo un problema desea resolver, podría sugerir el comando wget
:
cd c:\destination
wget --mirror --continue --no-host-directories --user=username --password=s3cr3t ftp://hostname/source/path/
La opción --continue
podría ser muy peligroso si los archivos cambio en el servidor. Si los archivos solo son añadidos, entonces es muy amigable.
Sin embargo, si se trata de un ejercicio de aprendizaje para usted y que le gustaría hacer su programa de trabajo, creo que usted debe comenzar por mirar esta línea:
for subdir, dirs, files in os.walk(directory):
directory
ha sido el directorio de origen remoto en la mayoría de su programa, pero la función os.walk()
no puede recorrer un directorio remoto . Necesita iterar sobre los archivos devueltos usted mismo, utilizando una devolución de llamada suministrada a la función retrlines
.
Eche un vistazo a las opciones MLSD
o NLST
en lugar de LIST
, probablemente sean más fáciles de analizar. (Tenga en cuenta que FTP no especifica cómo deberían verse las listas, siempre fue pensado para ser manejado por un humano en una consola, o un nombre de archivo específico transferido. Por lo tanto, los programas que hacen cosas inteligentes con listas de FTP se los presentan al usuario en una GUI probablemente tenga que tener enormes montones de códigos de casos especiales para servidores raros u oscuros. Y probablemente todos hagan algo estúpido cuando se enfrenten con nombres de archivos maliciosos.)
¿Se puede usar sftp
? sftp
tiene tiene una especificación de cómo se supone que se deben analizar los listados de archivos, no transmite el nombre de usuario/contraseña a la vista y no tiene la gran molestia de las conexiones pasivas vs activas; simplemente usa la conexión única, lo que significa que funciona en más firewalls que FTP.
Editar: Debe pasar un objeto 'invocable' a la función retrlines
. Un objeto invocable es una instancia de una clase que definió un método __call__
o una función. Si bien la función puede ser más fácil de describir, una instancia de una clase puede ser más útil. (Podría usar la instancia para recopilar los nombres de los archivos, pero la función tendría que escribir en una variable global.)
Aquí es uno de los objetos más simple exigible:
>>> class c:
... def __call__(self, *args):
... print(args)
...
>>> f = c()
>>> f('hello')
('hello',)
>>> f('hello', 'world')
('hello', 'world')
Esto crea una nueva clase, c
, que define un método de instancia __call__
. Esto solo imprime sus argumentos de una manera bastante estúpida, pero muestra cuán mínimo estamos hablando. :)
Si quería algo más inteligente, podría hacer algo como esto:
class handle_lines:
def __init__(self):
self.lines = []
def __call__(self, *args):
self.lines << args[0]
llamada iterlines
con un objeto de esta clase, a continuación, busque en lines
miembro del objeto para obtener más información.
@Sosti, la mención de la función 'retrlines' en mi publicación es un hipervínculo a la documentación :) – sarnold
Muchas gracias por eso, ¡todos suenan como sugerencias sólidas! Olvidé mencionar que estoy usando Python 2.5 en Windows XP (si es que eso es útil) Si uso la opción MLSD, 'ftp.retrlines (' MLSD ')', ¿funcionaría el código para la iteración o tendré que modificarlo? ¿Más? (seguro que suena un poco tonto pero nuevo aquí, ¿recuerdas?: DD) – Sosti
@Sosti, aún necesitarías modificar tu código: no puedes usar la función 'os.walk()'. Editaré mi respuesta en un momento para mostrar cómo hacer un objeto de devolución de llamada para 'retrlines'. – sarnold