2013-02-11 36 views
15

我想用Python上傳遠程服務器上的文件。我想事先檢查遠程路徑是否真的存在,如果不存在,則創建它。在僞代碼:在Python中使用SFTP上傳文件,但在路徑不存在的情況下創建目錄

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() 

但是,這種解決方案聽起來不太好,因爲我關閉連接,然後重新打開它。有沒有更好的方法來做到這一點?

+0

有關:[py.py中的ftp的os.renames](http://stackoverflow.com/q/14641267/4279) – jfs 2013-02-15 18:20:46

回答

26

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。

+0

它不處理不存在的父目錄('-p')。比較os.mkdir()和os.makedirs()。拆分路徑並進行遞歸調用以在必要時創建父目錄 – jfs 2013-02-11 20:09:12

+0

是的,同意的,將相應地更新。 – isedev 2013-02-11 20:59:26

+0

在函數mkdir_p中沒有句柄sftp – franzlorenzon 2013-02-12 09:16:44

5

簡單的東西稍微更具可讀性過於

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_) 
+0

+1提供非遞歸選擇。注意這裏的「remote」輸入參數是一個遠程文件路徑。如果您希望此功能將遠程目錄路徑作爲輸入,請將「dir_,basename = os.path.split(remote)」替換爲「dir_ = remote」。 – 2016-01-14 10:06:41

+0

@AlanEvangelista感謝您的評論。更新了傳遞一個標誌「is_dir」的代碼。如果需要請檢查和編輯。 – gabhijit 2016-01-15 04:52:29

1

有了這個今天做。這是我如何做到的。

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) 
相關問題