Python pysftp get\_r fra Linux fungerer fint på Linux, men ikke på Windows

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg vil gerne kopiere en hel katalogstruktur med filer og undermapper rekursivt ved hjælp af SFTP fra en Linux-server til en lokal maskine (både Windows og Linux) ved hjælp af Python 2.7.


Jeg kan pinge serveren og downloade filerne ved hjælp af WinSCP fra samme maskine.


Jeg prøvede følgende kode, fungerer fint på Linux, men ikke på Windows.


Jeg forsøgte , /, os.join, alle giver mig samme fejl, også kontrollerede tilladelser.


import os
import pysftp

cnopts = pysftp.CnOpts()
cnopts.hostkeys = None    # disable host key checking.
sftp=pysftp.Connection('xxxx.xxx.com', username='xxx',password='xxx',cnopts=cnopts)
sftp.get\_r('/abc/def/ghi/klm/mno', 'C:pqr',preserve\_mtime=False)


File "<stdin>", line 1, in <module> File "C:Python27libsite-packagespysftp\_init\_.py", line 311, in get\_r preserve\_mtime=preserve\_mtime)
File "C:Python27libsite-packagespysftp\_init\_.py", line 249, in get self.\_sftp.get(remotepath, localpath, callback=callback)
File "C:Python27libsite-packagesparamikosftp\_client.py", line 769, in get with open(localpath, 'wb') as fl: IOError: [Errno 2] No such file or directory: u'C:\pqr\./abc/def/ghi/klm/mno/.nfs0000000615c569f500000004' 

Bedste reference


Faktisk fungerer pysftp get\_r ikke på Windows. Det bruger funktionerne os.sep og os.path til fjerntliggende SFTP-stier, hvad er der galt, da SFTP-stier altid bruger en fremadrettet skråstreg.


Men du kan nemt implementere en bærbar udskiftning:


import os
from stat import S\_IMODE, S\_ISDIR, S\_ISREG

def get\_r\_portable(sftp, remotedir, localdir, preserve\_mtime=False):
    for entry in sftp.listdir(remotedir):
        remotepath = remotedir + "/" + entry
        localpath = os.path.join(localdir, entry)            
        mode = sftp.stat(remotepath).st\_mode
        if S\_ISDIR(mode):
            try:
                os.mkdir(localpath)
            except OSError:     # dir exists
                pass
            get\_r\_portable(sftp, remotepath, localpath, preserve\_mtime)
        elif S\_ISREG(mode):
            sftp.get(remotepath, localpath, preserve\_mtime=preserve\_mtime)


Brug det som:


get\_r\_portable(sftp, '/abc/def/ghi/klm/mno', 'C:\pqr', preserve\_mtime=False) 





Sidebesked: Ikke 'deaktiver verifikation af værtsnøgle' . Du mister en beskyttelse mod MITM-angreb. [12]


For at få en korrekt løsning, se Verificer værtsnøgle med pysftp.

Andre referencer 1


Hvis du har din ssh nøgle tilføjet i din nøglering, og du kan gøre passwordless ssh -


import subprocess
# source and destination will have to be in the
# cmdline format, something like this - "user@server:path"
p = subprocess.Popen(["scp", "-r", source, destination])
status = p.wait()


Hvis du ikke er i stand til at gøre passwordless ssh, så kan du bruge sftp\_client fra paramiko. [14]