paramikoを使って完全なディレクトリをどのように転送しますか? 私が使用しようとしている:私は、このエラーを与えているparamikoのディレクトリ転送
sftp.put("/Folder1","/Folder2")
- 私はあなたがそれを行うことができるとは思わない
Error : [Errno 21] Is a directory
paramikoを使って完全なディレクトリをどのように転送しますか? 私が使用しようとしている:私は、このエラーを与えているparamikoのディレクトリ転送
sftp.put("/Folder1","/Folder2")
- 私はあなたがそれを行うことができるとは思わない
Error : [Errno 21] Is a directory
これは、シャットルを使用していなかった場合と同じように、ローカルでPythonを使用する場合と同様に行う必要があります。
os.walk()
とsftp.mkdir()
とsftp.put()
を組み合わせてください。また、シンボリックリンクを解決するかどうかによって、各ファイルとディレクトリをで確認することもできます。
を。 os.walk
のドキュメントを参照し、各ファイルを「手動で」コピーします。
私が知る限り、Paramikoは再帰的ファイルアップロードをサポートしていません。しかし、私はsolution for recursive upload using Paramiko hereを見つけました。その再帰アップロード機能の抜粋を次に示します。
def _send_recursive(self, files):
for base in files:
lastdir = base
for root, dirs, fls in os.walk(base):
# pop back out to the next dir in the walk
while lastdir != os.path.commonprefix([lastdir, root]):
self._send_popd()
lastdir = os.path.split(lastdir)[0]
self._send_pushd(root)
lastdir = root
self._send_files([os.path.join(root, f) for f in fls])
あなたがしようといずれかの再帰的なアップロードのため上記の関数を呼び出すその機能SCPClient.put
を使用するか、自分でそれを実装することができます。
sftp = self.client.open_sftp()
をparamikoのものに置き換えて、ここでlibcloud
を取り除くことができます。あなたはparamiko.SFTPClientをサブクラス化し、それに次のメソッドを追加することができます
import os.path
from stat import S_ISDIR
from libcloud.compute.ssh import SSHClient
from paramiko.sftp import SFTPError
class CloudSSHClient(SSHClient):
@staticmethod
def normalize_dirpath(dirpath):
while dirpath.endswith("/"):
dirpath = dirpath[:-1]
return dirpath
def mkdir(self, sftp, remotepath, mode=0777, intermediate=False):
remotepath = self.normalize_dirpath(remotepath)
if intermediate:
try:
sftp.mkdir(remotepath, mode=mode)
except IOError, e:
self.mkdir(sftp, remotepath.rsplit("/", 1)[0], mode=mode,
intermediate=True)
return sftp.mkdir(remotepath, mode=mode)
else:
sftp.mkdir(remotepath, mode=mode)
def put_dir_recursively(self, localpath, remotepath, preserve_perm=True):
"upload local directory to remote recursively"
assert remotepath.startswith("/"), "%s must be absolute path" % remotepath
# normalize
localpath = self.normalize_dirpath(localpath)
remotepath = self.normalize_dirpath(remotepath)
sftp = self.client.open_sftp()
try:
sftp.chdir(remotepath)
localsuffix = localpath.rsplit("/", 1)[1]
remotesuffix = remotepath.rsplit("/", 1)[1]
if localsuffix != remotesuffix:
remotepath = os.path.join(remotepath, localsuffix)
except IOError, e:
pass
for root, dirs, fls in os.walk(localpath):
prefix = os.path.commonprefix([localpath, root])
suffix = root.split(prefix, 1)[1]
if suffix.startswith("/"):
suffix = suffix[1:]
remroot = os.path.join(remotepath, suffix)
try:
sftp.chdir(remroot)
except IOError, e:
if preserve_perm:
mode = os.stat(root).st_mode & 0777
else:
mode = 0777
self.mkdir(sftp, remroot, mode=mode, intermediate=True)
sftp.chdir(remroot)
for f in fls:
remfile = os.path.join(remroot, f)
localfile = os.path.join(root, f)
sftp.put(localfile, remfile)
if preserve_perm:
sftp.chmod(remfile, os.stat(localfile).st_mode & 0777)
ニース、完全な答え。ちょっとした点: 'str.rsplit'の代わりに' os.path.split'を使うことをお勧めします。また、 'normalize_path'メソッドを定義しますが、' put_dir_recursively'では 'suffix = suffix [1:]'を実行します。 –
:
import paramiko
import os
class MySFTPClient(paramiko.SFTPClient):
def put_dir(self, source, target):
''' Uploads the contents of the source directory to the target path. The
target directory needs to exists. All subdirectories in source are
created under target.
'''
for item in os.listdir(source):
if os.path.isfile(os.path.join(source, item)):
self.put(os.path.join(source, item), '%s/%s' % (target, item))
else:
self.mkdir('%s/%s' % (target, item), ignore_existing=True)
self.put_dir(os.path.join(source, item), '%s/%s' % (target, item))
def mkdir(self, path, mode=511, ignore_existing=False):
''' Augments mkdir by adding an option to not fail if the folder exists '''
try:
super(MySFTPClient, self).mkdir(path, mode)
except IOError:
if ignore_existing:
pass
else:
raise
作品私はこのような何かを行うため、すべてのフォルダとファイルがリモートサーバにコピーされます。ここで
parent = os.path.expanduser("~")
for dirpath, dirnames, filenames in os.walk(parent):
remote_path = os.path.join(remote_location, dirpath[len(parent)+1:])
try:
ftp.listdir(remote_path)
except IOError:
ftp.mkdir(remote_path)
for filename in filenames:
ftp.put(os.path.join(dirpath, filename), os.path.join(remote_path, filename))
はコードの私の作品です:
import errno
import os
import stat
def download_files(sftp_client, remote_dir, local_dir):
if not exists_remote(sftp_client, remote_dir):
return
if not os.path.exists(local_dir):
os.mkdir(local_dir)
for filename in sftp_client.listdir(remote_dir):
if stat.S_ISDIR(sftp_client.stat(remote_dir + filename).st_mode):
# uses '/' path delimiter for remote server
download_file(sftp_client, remote_dir + filename + '/', os.path.join(local_dir, filename))
else:
if not os.path.isfile(os.path.join(local_dir, filename)):
sftp_client.get(remote_dir + filename, os.path.join(local_dir, filename))
def exists_remote(sftp_client, path):
try:
sftp_client.stat(path)
except IOError, e:
if e.errno == errno.ENOENT:
return False
raise
else:
return True
これが私の最初のStackOverflowの答えです。私は今日これに似た仕事をしていました。ですから、私はPythonとparamikoを使ってWindowsからLinuxにフォルダ全体をコピーする直接的な方法を見つけようとしました。ちょっとした調査の後、サブフォルダとファイルを含む小さなサイズのフォルダで動作するこのソリューションを思いつきました。
このソリューションは、まず現在のフォルダ(ここではos.walk()が役に立ちます)のzipファイルを作成してから、コピー先のサーバにコピーして解凍します。
zipHere = zipfile.ZipFile("file_to_copy.zip", "w")
for root, folders, files in os.walk(FILE_TO_COPY_PATH):
for file in files:
zipHere.write(os.path.join(root, file), arcname=os.path.join(os.path.relpath(root, os.path.dirname(FILE_TO_COPY_PATH)), file))
for folder in folders:
zipHere.write(os.path.join(root, folder), arcname=os.path.join(os.path.relpath(root, os.path.dirname(FILE_TO_COPY_PATH)), folder))
zipHere.close()
# sftp is the paramiko.SFTPClient connection
sftp.put('local_zip_file_location','remote_zip_file_location')
# telnet_conn is the telnetlib.Telnet connection
telnet_conn.write('cd cd_to_zip_file_location')
telnet_conn.write('unzip -o file_to_copy.zip')
os.walk()はこの問題を解決する正しい方法ですが、SCP固有の方法で処理するため、これを正確にコピーしないでください。 SFTPは少し違った働きをしています(免責事項、私はそのコードを書いています) – JimB
@Martin Kosek - あなたの答えは気に入っていますが、解決策へのリンクが壊れているようです。編集して修正できますか?ありがとう。 – RobertMS
@RobertMS - そうですね、私はPythonモジュールが削除されたのを見ています。この場合、私はJimBのソリューションがos.walk()、sftp.mkdir()、sftp.put()のベスト・コンビネーションになると思います。 –