Python의 ftplib를 사용하여 이식 가능한 디렉토리 목록 가져오기
-
02-07-2019 - |
문제
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
...
Python 3.3부터 ftplib는 이를 수행하기 위한 특정 방법을 제공합니다:
파일 이름, 마지막 수정 스탬프, 파일 크기 등을 얻으려고 시도하는 동안 여기에서 길을 찾았고 내 코드를 추가하고 싶었습니다.구문 분석을 위한 루프를 작성하는 데 몇 분 밖에 걸리지 않았습니다. ftp.dir(dir_list.append)
Python 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
응답.가장 많이 사용되는 레이아웃을 처리하려면 코드를 작성해야 합니다.저는 리눅스부터 시작하겠습니다. ls
그리고 윈도우 서버 DIR
형식.하지만 거기에는 다양한 종류가 있습니다.
다시 nlst
메서드(결과 반환 NLST
명령) 더 긴 목록을 구문 분석할 수 없는 경우.보너스 포인트를 얻으려면 다음을 치트하세요.아마도 알려진 파일 이름이 포함된 줄에서 가장 긴 숫자는 해당 파일의 길이일 것입니다.
MLSD를 지원하지 않는 FTP 서버(Rackspace Cloud Sites 가상 서버)에 문제가 생겼습니다.하지만 파일 이름뿐만 아니라 크기, 타임스탬프 등 여러 파일 정보 필드가 필요하므로 DIR 명령을 사용해야 합니다.이 서버에서 DIR의 출력은 OP의 출력과 매우 유사합니다.누군가에게 도움이 된다면, 파일 이름, 크기 및 타임스탬프를 얻기 위해 그러한 출력의 한 줄을 구문 분석하는 작은 Python 클래스가 있습니다.
날짜/시간 가져오기
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')
이식성이 좋지는 않지만 다양한 FTP 서버를 처리하기 위해 확장하거나 수정하기는 쉽습니다.
이것은 Python 문서에서 가져온 것입니다.
>>> 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
그것은 내 코드에 도움이 되었습니다.
어떤 종류의 파일만 펠터링하고 각 줄마다 테스트하는 조건을 추가하여 화면에 표시하려고 했을 때.
이와 같이
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)