GreyHippo
GreyHippo

Reputation: 263

Error in folder names when using Pysftp to transfer files from Windows

I am using Pysftp to transfer files from a Windows server to a Buffalo Terastation. I would like to be able to tell it to transfer all files in a folder using the PUT_R command but when I run my code the files are transferred oddly.

My code:

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

When I run the code I get filenames on the Terastation that look like

photos\.\image1.jpg
photos\.\image2.jpg

I guess the code is not dealing with paths between platforms correctly. How can I correct the paths?

I have tried

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

But I get a "No Such File" error

Upvotes: 2

Views: 2314

Answers (2)

PlumsAhoy
PlumsAhoy

Reputation: 138

I got it working by (temporarily) changing to the source directory on the local machine, iterating over the files and then using put() instead of put_r(). You'll need to make sure the remote directory already exists though.

Here is some example code:

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)

Upvotes: 0

thestackexchangeguy
thestackexchangeguy

Reputation: 87

I created a hacky workaround for this problem. It is not very clever and it might not be stable in all cases. Therefore, please use with care. Tested on Python 3.x with 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")

Upvotes: 1

Related Questions