Подтвердить что ты не робот

Ftplib проверяет, является ли файл папкой?

Как я могу проверить, является ли файл на удаленном ftp папкой или не использует ftplib?

Лучший способ, которым я сейчас должен сделать nlst, и перебрать размер вызывающего файла на каждый из файлов, если ошибки файла отсутствуют, это папка?

Есть ли лучший способ? Я не могу разобрать вывод списка, так как существует около десятка разных ftp-серверов (многие очень старые.)

Что мне делать?

4b9b3361

Ответ 1

FTP является довольно элементарным протоколом, и нет встроенного протокола запроса, позволяющего получить тип (файл, dir) каждого узла, поэтому единственное решение - эвристика, подобная той, которую вы нашли.

Если получение размера каждого узла не работает, возможно, вам следует подумать о вызове FTP.nlst() на каждом из этих узлов: ошибками будут файлы, а не каталоги.

Ответ 2

В ftplib нет определений "isdir" и "isfile". Если вам не нужно использовать ftplib, я рекомендую использовать ftputil.

Прежде всего вам необходимо установить пакет ftputil. Чтобы достичь этого, используйте эту команду: python -m pip install ftputil. После установки вы можете импортировать библиотеку в свой код. Я думаю, что это достаточно объяснение. Итак, давайте перейдем к реализации:

import ftputil
with ftputil.FTPHost("host", "username", "password") as ftp_host:
    ftp_host.chdir("/directory/")   
    list = ftp_host.listdir(ftp_host.curdir)
    for fname in list:
        if ftp_host.path.isdir(fname):
            print(fname + " is a directory")
        else:
            print(fname + " is not a directory")

Ответ 3

FTP.dir возвращает список каталогов, в котором вы можете проанализировать функцию обратного вызова, чтобы узнать, является ли она каталогом. Например, например:

def parse(line):
    if line[0] == 'd':
        print(line.rpartition(' ')[2])   # gives you the name of a directory

ftp.dir(parse)

Ответ 4

Вы можете использовать команду MLST:

import ftplib
f = ftplib.FTP()
f.connect("localhost")
f.login()
print f.sendcmd('MLST /')

Против сервера pyftpdlib приведенный выше код:

250-Listing "/":
 modify=20111212124834;perm=el;size=12288;type=dir;unique=807g100001; /
250 End MLST.

Что вам нужно сделать, так это разобрать эту строку и искать "type = dir" или "type = cdir" (текущий каталог, как в "." ) или "type = pdir" (родительский каталог, как в ".." ) через регулярное выражение. Если вы получаете совпадение, это означает, что предоставленный путь относится к каталогу.

Ответ 5

def is_file(filename):
    return ftp.size(filename) is not None

Это работает, потому что ftp.size возвращает None, если это каталог.

Ответ 6

def is_file(filename):
    current = ftp.pwd()
    try:
        ftp.cwd(filename)
    except:
        ftp.cwd(current)
        return True
    ftp.cwd(current)
    return False

Вот еще одно решение. Половина пути, я понял, что это проблема. Если у вас нет разрешения на изменение в папку, он будет читать его как файл. Он будет работать, если у вас есть доступ к любой папке.

Я все еще размещал его, потому что, возможно, он даст некоторые идеи.

Ответ 7

Я использовал это при работе с ftplib:

import ftplib
from ftplib import FTP
ftp=FTP("ftp address")
ftp.login("user","password")

path = "/is/this/a/file/or/a/folder/"

try:
    ftp.cwd(path)
    print "it a folder!"
except ftplib.error_perm:
    print "it not a folder!"

Ответ 8

Это то, что я использую для поиска каталогов в данной директории. Я возвращаю имена каталогов в качестве набора, потому что позже я использую наборы в программе, но вы можете отказаться от создания набора в конце и вернуть имена каталогов в виде списка, кортежа и т.д.

def get_directories(ftp_server):
    """
    Returns a set of directories in the current directory on the FTP server

    Stdout output of ftp_server.dir() is redirected to an IO object and then
    reset, because ftp_server.dir() only prints its results to stdout.

    @param ftp_server: Open connection to FTP server
    @return: Set of directory names
    """
    # Redirect stdout
    old_stdout = sys.stdout
    sys.stdout = new_stdout = StringIO()
    # Get directory listing
    ftp_server.dir()
    # Reset stdout
    sys.stdout = old_stdout

    directory_listing = new_stdout.getvalue().split("\n")
    # Directories are listed starting with "d" for "directory"
    only_directories = (x for x in directory_listing if x.startswith("d"))
    # This only deals with directory names without spaces.
    directory_names = set(dirname.split()[-1] for dirname in only_directories)
    return directory_names

Ответ 9

Я нашел решение, но оно может быть не лучшим, и я думаю, что это может быть полезно для вас.

> def isfile(remote_name):
>     try:
>         ftp.sendcmd('MDTM ' + remote_name)
>     except:
>         return False
>     else:
>         return True

Эта функция вернет TRUE, если "remote_name" является обычным файлом, иначе вернется False.

Ответ 10

Все мое решение выглядит так:

def is_file(filename):
    try:
        ftp.cwd(filename)
    except Exception as e:
        if "550" in e:
            return True
    return False

Ответ 11

ftp_conn = FTP(host=host_name, user=user_name, passwd=password, acct='', timeout=None, source_address=None)
ftp_conn.cwd(path_ftp)
for data_dir in ftp_conn.mlsd():
    print(data_dir)

Вывод:

('3', {'modify': '20170719134928', 'perm': 'flcdmpe', 'type': 'dir', 'unique': '804U485826E', 'unix.group': '10000', 'unix.mode': '0755', 'unix.owner': '10754'})

see 'type': 'dir'

Ответ 12

def _get_file_type(self, path):
    """
Returns string parsed from MLST command
    """
    try:
        return_str = self.ftp.sendcmd('MLST ' + path)
    except BaseException as e:
        raise BaseException("No such file or directory")
    c = re.search('Type=(dir|file);', return_str)
    try:
        filetype = c.group(1)
    except AttributeError as e:
        raise BaseException("Unable to parse")
    return filetype


def is_file(self,path):
    """
Returns if a filepath is a file
    """
    filetype = self._get_file_type(path)
    if filetype == 'file':
        return True
    return False

Ответ 13

Эта функция возвращает True, если object является файлом, в противном случае возвращает False.

def _is_file(FTP, object):
    if FTP.nlst(object) == [object]:
        return True
    else:
        return False

Пример использования:

import ftplib

with ftplib.FTP(host=ftp_link, user=ftp_username, passwd=ftp_password) as FTP:
    if _is_file(FTP, object='/path/filename.extention'):
        print(object, 'is file!')
    else:
        print(object, 'is directory!')

Как работает FTP.nlst()?

  1. FTP.nlst(object) возвращает [object], если object является файлом.
  2. FTP.nlst(object) возвращает пустой список, если object является пустой папкой.
  3. FTP.nlst(object) возвращает список строк, если object является папкой с файлами или каталогами.

Ответ 14

Все файлы имеют расширение, поэтому с помощью split ('.') его можно разбить на список размера 2. В то время как для каталогов размер списка будет один после использования split ('.'). Поэтому, проверяя размер списка, мы можем определить, есть ли его файл или каталог.

os.chdir(r"path")
ftp = ftplib.FTP('ftp.some.server')
ftp.login('username','password')
filelist=ftp.nlst()
for file in filelist:
    fildir=file.split('.')
    filsize=len(fildir)
    if(filsize>1):
        ftp.retrbinary('RETR %s' %file, open(file, 'wb').write)
ftp.close()