15

私はPythonでftp経由でファイルを転送するためにpycurlを使用していました。次を使用して、リモートサーバー上に不足しているディレクトリを自動的に作成できます。

c.setopt(pycurl.FTP_CREATE_MISSING_DIRS, 1)

何らかの理由で、ftplibに切り替える必要があります。しかし、私はここで同じことをする方法がわかりません。それを行うためにstorbinary関数に追加するオプションはありますか?または、ディレクトリを手動で作成する必要がありますか?

4

7 に答える 7

22

FTP_CREATE_MISSING_DIRSはcurl操作です(ここに追加されます)。ftplibを使用して手動で行う必要があると推測するのは危険ですが、間違っていることが証明されることを望んでいます。

私は次のようなことをします:(テストされておらず、キャッチする必要がありますftplib.all_errors

ftp = ... # Create connection

# Change directories - create if it doesn't exist
def chdir(dir): 
    if directory_exists(dir) is False: # (or negate, whatever you prefer for readability)
        ftp.mkd(dir)
    ftp.cwd(dir)

# Check if directory exists (in current location)
def directory_exists(dir):
    filelist = []
    ftp.retrlines('LIST',filelist.append)
    for f in filelist:
        if f.split()[-1] == dir and f.upper().startswith('D'):
            return True
    return False

または、次のようにすることもできますdirectory_exists:(少し読みにくいですか?)

# Check if directory exists (in current location)
def directory_exists(dir):
    filelist = []
    ftp.retrlines('LIST',filelist.append)
    return any(f.split()[-1] == dir and f.upper().startswith('D') for f in filelist)
于 2012-05-22T05:03:33.620 に答える
16

ちょっと古い投稿だとは思いますが、これが必要だったので、とてもシンプルな機能を思いつきました。私はPythonを初めて使用するので、フィードバックをいただければ幸いです。

from ftplib import FTP

ftp = FTP('domain.com', 'username', 'password')

def cdTree(currentDir):
    if currentDir != "":
        try:
            ftp.cwd(currentDir)
        except IOError:
            cdTree("/".join(currentDir.split("/")[:-1]))
            ftp.mkd(currentDir)
            ftp.cwd(currentDir)

使用例:

cdTree("/this/is/an/example")
于 2013-08-20T18:14:33.613 に答える
4

これを@AlexLの回答にコメントとして追加してみましたが、長すぎました。途中でディレクトリを作成したい場合は、ディレクトリを変更するときに再帰的に下降する必要があります。例えば

def chdir(ftp, directory):
    ch_dir_rec(ftp,directory.split('/')) 

# Check if directory exists (in current location)
def directory_exists(ftp, directory):
    filelist = []
    ftp.retrlines('LIST',filelist.append)
    for f in filelist:
        if f.split()[-1] == directory and f.upper().startswith('D'):
            return True
    return False

def ch_dir_rec(ftp, descending_path_split):
    if len(descending_path_split) == 0:
        return

    next_level_directory = descending_path_split.pop(0)

    if not directory_exists(ftp,next_level_directory):
        ftp.mkd(next_level_directory)
    ftp.cwd(next_level_directory)
    ch_dir_rec(ftp,descending_path_split)
于 2013-03-22T01:52:09.467 に答える
1

別の方法は、各パス要素をループし、次の要素を作成して、新しく作成されたディレクトリに変更することです。あるFTPサーバーから別のFTPサーバーにアイテムをコピーしていたので、私のユースケースはかなり単純でした。

def create_ftp_path(session: ftplib.FTP, required_dir: str):
    required_dir = required_dir.split('/')[:-1]
    for path_item in required_dir:
        if path_item.strip() == '':
            continue
        path_item = path_item.replace('/', '')
        try:
            session.cwd(path_item)
        except:
            session.mkd(path_item)
            session.cwd(path_item)

考慮事項:

  • この関数は、FTPセッションのディレクトリをすでにいくつかのベースパスに変更しており、required_dirがそのベースパスからのパスであることを前提としています。
  • required_dir最後の要素としてファイル名が含まれます。
  • /私の場合、553 permission denied例外が発生していたため、文字を削除しています。
  • 例外処理が不足していますが、私の場合、アップロードの検証はコード内でさらに行われているため、失敗した場合でも、さらにダウンしてキャッチされます。
于 2021-03-23T10:43:41.420 に答える
0

このコードは、パスに欠落しているすべてのフォルダーを作成します。

...

def chdir(ftp_path, ftp_conn):
    dirs = [d for d in ftp_path.split('/') if d != '']
    for p in dirs:
        print(p)
        check_dir(p, ftp_conn)


def check_dir(dir, ftp_conn):
    filelist = []
    ftp_conn.retrlines('LIST', filelist.append)
    found = False

    for f in filelist:
        if f.split()[-1] == dir and f.lower().startswith('d'):
            found = True

    if not found:
        ftp_conn.mkd(dir)
    ftp_conn.cwd(dir)

if __name__ == '__main__':
    ftp_conn = ... # ftp connection
    t = 'FTP/for_Vadim/1/2/3/'

    chdir(t, ftp_conn)

このコードは、パス内のすべてのdirをチェックし、欠落しているdirを作成します

「FTP/for_Vadim/」の前「FTP/for_Vadim /1/2/3/」の後

于 2014-03-20T10:35:23.883 に答える
0

私はこのようなものを使用しています(cwdなし):

# -*- coding:utf-8 -*-

from ftplib import FTP, error_perm


def createDirs(ftp, dirpath):
    """
    Create dir with subdirs.

    :param ftp:     connected FTP
    :param dirpath: path (like 'test/test1/test2')

    :type ftp:      FTP
    :type dirpath:  str
    :rtype:         None

    """

    dirpath = dirpath.replace('\\', '/')
    tmp = dirpath.split('/')
    dirs = []

    for _ in tmp:
        if len(dirs) == 0:
            dirs.append(_)
            continue

        dirs.append(dirs[-1] + '/' + _)

    for _ in dirs:
        try:
            ftp.mkd(_)
        except error_perm as e:
            e_str = str(e)
            if '550' in e_str and 'File exists' in e_str:
                continue


if __name__ == '__main__':
    # init ftp
    createDirs(ftp=ftp, dirpath='test/1/2/3')
于 2018-09-07T12:41:02.077 に答える
0

FTPファイルコピーの欠落しているディレクトリパスを解決するために次の行を使用しています

import os
ftps = FTP_TLS('ftps_server')
ftps.connect()
ftps.login()

destination_dir_path = 'some/dir/path'          # directory path on FTP
dir_path = ''
for i in destination_dir_path.split('/'):
    dir_path = os.path.join(dir_path,i)
    if i not in ftps.nlst(os.path.dirname(dir_path)):
        ftps.mkd(dir_path)                      # create directory on the FTP
ftps.storbinary(...)                            # store file using the binary mode
于 2020-09-10T13:57:11.380 に答える