Ошибка в именах папок при использовании Pysftp для передачи файлов из Windows

#python #pysftp

#python #pysftp

Вопрос:

Я использую Pysftp для передачи файлов с сервера Windows на сервер Buffalo Terastation. Я хотел бы иметь возможность указать ему передавать все файлы в папке с помощью команды PUT_R, но когда я запускаю свой код, файлы передаются странно.

Мой код:

 srv.put_r('c:/temp1/photos', 'array1/test_sftp/photos', preserve_mtime=True)
  

Когда я запускаю код, я получаю имена файлов на Terastation, которые выглядят как

 photos.image1.jpg
photos.image2.jpg
  

Я предполагаю, что код неправильно обрабатывает пути между платформами. Как я могу исправить пути?

Я пробовал

 dest = dest.replace('\.\','/')
  

Но я получаю сообщение об ошибке «Такого файла нет»

Комментарии:

1. Может быть, я говорю глупости, но это c:/temp1/photos путь в стиле Windows?

2. @Gjhuizing да, Windows / DOS принимали прямые косые черты в течение тридцати лет до MS-DOS 2.0

3. Хорошо, спасибо, жаль, что я не знал об этом, когда использовал Windows 😉

4. У меня такая же проблема, хотелось бы увидеть обобщенный ответ.

Ответ №1:

Я создал хакерский обходной путь для этой проблемы. Это не очень умно и может быть нестабильным во всех случаях. Поэтому, пожалуйста, используйте с осторожностью. Протестировано на Python 3.x с pysftp 0.2.9.

 import os
import pysftp

# copy all folders (non-recursively) from from_dir (windows file system) to to_dir (linux file system)
def copy_files(host, user, pw, from_dir, to_dir):
    cnopts = pysftp.CnOpts()
    cnopts.hostkeys = None
    with pysftp.Connection(host=host, username=user, password=pw, cnopts=cnopts) as sftp:
        from_dir = os.path.normpath(from_dir)
        to_dir = "/"   os.path.normpath(to_dir).replace("\", "/").strip("/")
        top_folder = os.path.split(to_dir)[1]
        files = [file for file in os.listdir(from_dir) if os.path.isfile(os.path.join(from_dir, file))]
        for file in files:
            sftp.cwd(to_dir)
            sftp.put(os.path.join(from_dir, file), os.path.join("./{}".format(top_folder), file))
            sftp.execute(r'mv "{2}/{0}{1}" "{2}/{1}"'.format(top_folder, file, to_dir))

# usage: always use full paths for all directories
copy_files("hostname", "username", "password", "D:/Folder/from_folder", "/root/Documents/to_folder")
  

Ответ №2:

Я заставил его работать, (временно) перейдя в исходный каталог на локальном компьютере, выполнив итерацию по файлам, а затем используя put() вместо put_r() . Однако вам нужно убедиться, что удаленный каталог уже существует.

Вот несколько примеров кода:

 import os
import pysftp

cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
srv = pysftp.Connection(host=host, username=username, password=password, cnopts=cnopts)

local_folder = 'c:/temp1/photos'
remote_folder = 'array1/test_sftp/photos'

with pysftp.cd(local_folder):
    srv.cwd(remote_folder)
    for filename in os.listdir('.'):
        srv.put(filename, preserve_mtime=True)