2013-02-11 42 views
15

मैं पाइथन के साथ रिमोट सर्वर पर एक फ़ाइल अपलोड करना चाहता हूं। अगर मैं दूरस्थ पथ वास्तव में मौजूद हूं, और यदि ऐसा नहीं है, तो इसे पहले से जांचना चाहूंगा। स्यूडोकोड में:पायथन में एसएफटीपी का उपयोग कर फाइल अपलोड करें, लेकिन यदि पथ मौजूद नहीं है तो निर्देशिका बनाएं

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

लेकिन यह समाधान मेरे लिए अच्छा नहीं लगता है, क्योंकि मैं कनेक्शन बंद करता हूं और फिर इसे दोबारा खोलता हूं। इसे करने का कोई बेहतर तरीका है? (... chdir, mkdir, आदि) उन

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

+0

संबंधित: (http://stackoverflow.com/q/14641267/4279) – jfs

उत्तर

26

SFTP सामान्य एफ़टीपी आदेशों का समर्थन करता है, तो का उपयोग करें::

+0

यह गैर-मौजूदा मूल निर्देशिका ('-p') को संभाल नहीं करता है। Os.mkdir() बनाम os.makedirs() की तुलना करें। पथ को विभाजित करें और आवश्यक होने पर पैरेंट निर्देशिका बनाने के लिए रिकर्सिव कॉल करें – jfs

+0

हाँ, सहमत है, तदनुसार अपडेट होगा। – isedev

+0

फ़ंक्शन mkdir_p में sftp – franzlorenzon

1

Paramiko एक 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 को पूरी तरह अनुकरण करने के लिए, आप दूरस्थ_पैथ के माध्यम से रिकर्सिवली के माध्यम से काम कर सकते हैं:

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

बेशक, अगर दूरस्थ_पथ में एक दूरस्थ फ़ाइल नाम भी शामिल है, तो इसे विभाजित करने की आवश्यकता है, निर्देशिका mkdir_p पर पास की जा रही है और '।' के बजाय उपयोग किए गए फ़ाइल नाम sftp.put में।

+1

मैं जानता हूँ कि [अजगर में एफ़टीपी के लिए os.renames]। लेकिन क्या यह एक मौजूदा पथ के मामले को संभालता है? – franzlorenzon

+1

मेरे उत्तर में कोड देखें ... – isedev

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 काम करता है। ध्यान दें कि यहां "रिमोट" इनपुट पैरामीटर एक दूरस्थ फ़ाइल पथ है।यदि आप चाहते हैं कि इस फ़ंक्शन के बजाय इनपुट के रूप में दूरस्थ निर्देशिका पथ हो, तो "dir_ = basename = os.path.split (दूरस्थ)" को "dir_ = remote" के साथ बदलें। –

+0

@AlanEvangelista टिप्पणी के लिए धन्यवाद। एक ध्वज 'is_dir' पास करने वाले कोड को अपडेट किया गया। यदि आवश्यक हो तो कृपया समीक्षा करें और संपादित करें। – gabhijit

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)