33

Python を使用してリモート サーバーにファイルをアップロードしたいと考えています。リモートパスが本当に存在するかどうかを事前に確認し、存在しない場合は作成したいと思います。擬似コード:

if(remote_path not exist):
    create_path(remote_path)
upload_file(local_file, remote_path)

Paramikoでコマンドを実行してパスを作成することを考えていました(例mkdir -p remote_path)。私はこれを思いついた:

# I didn't test this code

import paramiko, sys

ssh = paramiko.SSHClient()
ssh.connect(myhost, 22, myusername, mypassword)
ssh.exec_command('mkdir -p ' + remote_path)
ssh.close

transport = paramiko.Transport((myhost, 22))
transport.connect(username = myusername, password = mypassword)

sftp = paramiko.SFTPClient.from_transport(transport)
sftp.put(local_path, remote_path)
sftp.close()

transport.close()

しかし、接続を閉じてから再度開くため、この解決策は私には良くありません。それを行うより良い方法はありますか?

4

7 に答える 7

58

SFTP は通常の FTP コマンド (chdir、mkdir など) をサポートしているため、次のコマンドを使用します。

sftp = paramiko.SFTPClient.from_transport(transport)
try:
    sftp.chdir(remote_path)  # Test if remote_path exists
except IOError:
    sftp.mkdir(remote_path)  # Create remote_path
    sftp.chdir(remote_path)
sftp.put(local_path, '.')    # At this point, you are in remote_path in either case
sftp.close()

を完全にエミュレートするmkdir -pには、remote_path を再帰的に処理します。

import os.path

def mkdir_p(sftp, remote_directory):
    """Change to this directory, recursively making new folders if needed.
    Returns True if any folders were created."""
    if remote_directory == '/':
        # absolute path so change directory to root
        sftp.chdir('/')
        return
    if remote_directory == '':
        # top-level relative directory must exist
        return
    try:
        sftp.chdir(remote_directory) # sub-directory exists
    except IOError:
        dirname, basename = os.path.split(remote_directory.rstrip('/'))
        mkdir_p(sftp, dirname) # make parent directories
        sftp.mkdir(basename) # sub-directory missing, so created it
        sftp.chdir(basename)
        return True

sftp = paramiko.SFTPClient.from_transport(transport)
mkdir_p(sftp, remote_path) 
sftp.put(local_path, '.')    # At this point, you are in remote_path
sftp.close()

もちろん、remote_path にリモート ファイル名も含まれている場合は、分割する必要があります。ディレクトリは mkdir_p に渡され、ファイル名は「.」の代わりに使用されます。sftp.put で。

于 2013-02-11T19:57:29.460 に答える
8

よりシンプルで少し読みやすいものも

def mkdir_p(sftp, remote, is_dir=False):
    """
    emulates mkdir_p if required. 
    sftp - is a valid sftp object
    remote - remote path to create. 
    """
    dirs_ = []
    if is_dir:
        dir_ = remote
    else:
        dir_, basename = os.path.split(remote)
    while len(dir_) > 1:
        dirs_.append(dir_)
        dir_, _  = os.path.split(dir_)

    if len(dir_) == 1 and not dir_.startswith("/"): 
        dirs_.append(dir_) # For a remote path like y/x.txt 

    while len(dirs_):
        dir_ = dirs_.pop()
        try:
            sftp.stat(dir_)
        except:
            print "making ... dir",  dir_
            sftp.mkdir(dir_)
于 2013-12-06T11:25:49.647 に答える
6

今日これをしなければならなかった。これが私がやった方法です。

def mkdir_p(sftp, remote_directory):
    dir_path = str()
    for dir_folder in remote_directory.split("/"):
        if dir_folder == "":
            continue
        dir_path += r"/{0}".format(dir_folder)
        try:
            sftp.listdir(dir_path)
        except IOError:
            sftp.mkdir(dir_path)
于 2015-01-28T18:47:32.283 に答える
1

Paramiko には mkdir 関数が含まれています。

http://paramiko-docs.readthedocs.org/en/latest/api/sftp.html#paramiko.sftp_si.SFTPServerInterface.mkdir

于 2013-02-11T19:55:44.073 に答える