programing

Python의 ftplib를 사용하여 이식 가능한 디렉토리 목록 가져 오기

firstcheck 2021. 1. 17. 10:55
반응형

Python의 ftplib를 사용하여 이식 가능한 디렉토리 목록 가져 오기


Python에서 완전한 FTP 지원을 위해 ftplib를 사용할 수 있습니다. 그러나 디렉토리 목록을 얻는 데 선호되는 방법은 다음과 같습니다.

# File: ftplib-example-1.py

import ftplib

ftp = ftplib.FTP("www.python.org")
ftp.login("anonymous", "ftplib-example-1")

data = []

ftp.dir(data.append)

ftp.quit()

for line in data:
    print "-", line

결과 :

$ python ftplib-example-1.py
- total 34
- drwxrwxr-x  11 root     4127         512 Sep 14 14:18 .
- drwxrwxr-x  11 root     4127         512 Sep 14 14:18 ..
- drwxrwxr-x   2 root     4127         512 Sep 13 15:18 RCS
- lrwxrwxrwx   1 root     bin           11 Jun 29 14:34 README -> welcome.msg
- drwxr-xr-x   3 root     wheel        512 May 19  1998 bin
- drwxr-sr-x   3 root     1400         512 Jun  9  1997 dev
- drwxrwxr--   2 root     4127         512 Feb  8  1998 dup
- drwxr-xr-x   3 root     wheel        512 May 19  1998 etc
...

아이디어는 결과를 구문 분석하여 디렉토리 목록을 얻는 것입니다. 그러나이 목록은 FTP 서버의 목록 형식 지정 방식에 직접적으로 의존합니다. FTP 서버가이 목록을 형식화 할 수있는 모든 다른 방법을 예상해야하는 코드를 작성하는 것은 매우 지저분 할 것입니다.

디렉토리 목록으로 배열을 채우는 이식 가능한 방법이 있습니까?

(어레이에는 폴더 이름 만 있어야합니다.)


을 사용해보십시오 ftp.nlst(dir).

그러나 폴더가 비어 있으면 오류가 발생할 수 있습니다.

files = []

try:
    files = ftp.nlst()
except ftplib.error_perm, resp:
    if str(resp) == "550 No files found":
        print "No files in this directory"
    else:
        raise

for f in files:
    print f

FTP 디렉토리 목록을 구문 분석하는 신뢰할 수 있고 표준화 된 방법은 MLSD 명령을 사용하는 것입니다. 이제 모든 최신 / 괜찮은 FTP 서버에서 지원해야합니다.

import ftplib
f = ftplib.FTP()
f.connect("localhost")
f.login()
ls = []
f.retrlines('MLSD', ls.append)
for entry in ls:
    print entry

위의 코드는 다음과 같이 인쇄됩니다.

modify=20110723201710;perm=el;size=4096;type=dir;unique=807g4e5a5; tests
modify=20111206092323;perm=el;size=4096;type=dir;unique=807g1008e0; .xchat2
modify=20111022125631;perm=el;size=4096;type=dir;unique=807g10001a; .gconfd
modify=20110808185618;perm=el;size=4096;type=dir;unique=807g160f9a; .skychart
...

파이썬 3.3부터 ftplib는이를 수행하는 특정 방법을 제공합니다.


파일 이름, 마지막으로 수정 된 스탬프, 파일 크기 등을 얻으려고하는 동안 여기에서 내 길을 찾았고 내 코드를 추가하고 싶었습니다. (텍스트 줄을 정리하기 ftp.dir(dir_list.append)위해) 파이썬 std lib를 사용 하여 구문 분석하고 배열을 만드는 루프를 작성하는 데 몇 분 밖에 걸리지 않았습니다 .strip()split()

ftp = FTP('sick.domain.bro')
ftp.login()
ftp.cwd('path/to/data')

dir_list = []
ftp.dir(dir_list.append)

# main thing is identifing which char marks start of good stuff
# '-rw-r--r--   1 ppsrt    ppsrt      545498 Jul 23 12:07 FILENAME.FOO
#                               ^  (that is line[29])

for line in dir_list:
   print line[29:].strip().split(' ') # got yerself an array there bud!
   # EX ['545498', 'Jul', '23', '12:07', 'FILENAME.FOO']

LIST응답 레이아웃에 대한 표준은 없습니다 . 가장 인기있는 레이아웃을 처리하려면 코드를 작성해야합니다. Linux ls및 Windows Server DIR형식으로 시작하겠습니다 . 그러나 거기에는 많은 다양성이 있습니다.

Fall back to the nlst method (returning the result of the NLST command) if you can't parse the longer list. For bonus points, cheat: perhaps the longest number in the line containing a known file name is its length.


I happen to be stuck with an FTP server (Rackspace Cloud Sites virtual server) that doesn't seem to support MLSD. Yet I need several fields of file information, such as size and timestamp, not just the filename, so I have to use the DIR command. On this server, the output of DIR looks very much like the OP's. In case it helps anyone, here's a little Python class that parses a line of such output to obtain the filename, size and timestamp.

import datetime

class FtpDir:
    def parse_dir_line(self, line):
        words = line.split()
        self.filename = words[8]
        self.size = int(words[4])
        t = words[7].split(':')
        ts = words[5] + '-' + words[6] + '-' + datetime.datetime.now().strftime('%Y') + ' ' + t[0] + ':' + t[1]
        self.timestamp = datetime.datetime.strptime(ts, '%b-%d-%Y %H:%M')

Not very portable, I know, but easy to extend or modify to deal with various different FTP servers.


This is from Python docs

>>> from ftplib import FTP_TLS
>>> ftps = FTP_TLS('ftp.python.org')
>>> ftps.login()           # login anonymously before securing control 
channel
>>> ftps.prot_p()          # switch to secure data connection
>>> ftps.retrlines('LIST') # list directory content securely
total 9
drwxr-xr-x   8 root     wheel        1024 Jan  3  1994 .
drwxr-xr-x   8 root     wheel        1024 Jan  3  1994 ..
drwxr-xr-x   2 root     wheel        1024 Jan  3  1994 bin
drwxr-xr-x   2 root     wheel        1024 Jan  3  1994 etc
d-wxrwxr-x   2 ftp      wheel        1024 Sep  5 13:43 incoming
drwxr-xr-x   2 root     wheel        1024 Nov 17  1993 lib
drwxr-xr-x   6 1094     wheel        1024 Sep 13 19:07 pub
drwxr-xr-x   3 root     wheel        1024 Jan  3  1994 usr
-rw-r--r--   1 root     root          312 Aug  1  1994 welcome.msg

That helped me with my code.

When I tried feltering only a type of files and show them on screen by adding a condition that tests on each line.

Like this

elif command == 'ls':
    print("directory of ", ftp.pwd())
    data = []
    ftp.dir(data.append)

    for line in data:
        x = line.split(".")
        formats=["gz", "zip", "rar", "tar", "bz2", "xz"]
        if x[-1] in formats:
            print ("-", line)

ReferenceURL : https://stackoverflow.com/questions/111954/using-pythons-ftplib-to-get-a-directory-listing-portably

반응형