Если это просто проблема, которую вы хотите решить, я могу предложить команду wget
:
cd c:\destination
wget --mirror --continue --no-host-directories --user=username --password=s3cr3t ftp://hostname/source/path/
Параметр --continue
может быть очень опасным, если файлы изменяются на сервере. Если файлы только когда-либо добавляются, это очень удобно.
Однако, если это обучающее упражнение для вас и вы хотите, чтобы ваша программа работала, я думаю, вам следует начать с рассмотрения этой строки:
for subdir, dirs, files in os.walk(directory):
directory
был удаленным исходным каталогом в большей части вашей программы, но функция os.walk()
не может пройти по удаленному каталогу. Вам необходимо выполнить итерацию по возвращенным файлам самостоятельно, используя обратный вызов, предоставленный retrlines
функция.
Взгляните на параметры MLSD
или NLST
вместо LIST
, их, вероятно, будет легче разобрать. (Обратите внимание, что FTP на самом деле не определяет, как должны выглядеть списки; он всегда предназначался для управления человеком с консоли или передачи определенного имени файла. Поэтому программы, которые делают умные вещи со списками FTP, например, представляют их пользователю в GUI, вероятно, должен иметь огромные груды специального кода для странных или малоизвестных серверов. И все они, вероятно, делают что-то глупое, сталкиваясь с вредоносными именами файлов.)
Можете ли вы использовать вместо него sftp
? sftp
имеет спецификацию того, как предполагается анализировать списки файлов, не передает имя пользователя / пароль в открытом виде и не вызывает огромного раздражения пассивных и активных подключений - это просто использует одно соединение, что означает, что он работает через большее количество брандмауэров, чем FTP.
Изменить: вам нужно передать "вызываемый" объект в retrlines
функцию. Вызываемый объект - это либо экземпляр класса, который определил __call__
метод, либо функцию. Хотя функцию может быть проще описать, экземпляр класса может быть более полезным. (Вы можете использовать экземпляр для сбора имен файлов, но функция должна будет записывать в глобальную переменную. Плохо.)
Вот один из самых простых вызываемых объектов:
>>> class c:
... def __call__(self, *args):
... print(args)
...
>>> f = c()
>>> f('hello')
('hello',)
>>> f('hello', 'world')
('hello', 'world')
Это создает новый класс c
, который определяет метод экземпляра __call__
. Это просто выводит свои аргументы в довольно глупой форме, но показывает, насколько мы минималистичны. :)
Если бы вы хотели чего-то более умного, оно могло бы сделать что-то вроде этого:
class handle_lines:
def __init__(self):
self.lines = []
def __call__(self, *args):
self.lines << args[0]
Вызовите iterlines
с объектом этого класса, а затем посмотрите подробности в члене lines
объекта.
person
sarnold
schedule
08.03.2011