2009-07-08 7 views
13

Używam tego skryptu, aby połączyć się z serwerem FTP i próby listy dostępnych katalogach:Jak sprawić, by Python sprawdzał, czy istnieje katalog ftp?

from ftplib import FTP 
ftp = FTP('ftp.cwi.nl') # connect to host, default port (some example server, i'll use other one) 
ftp.login()    # user anonymous, passwd [email protected] 
ftp.retrlines('LIST')  # list directory contents 
ftp.quit() 

Jak używać ftp.retrlines wyjściowych („LISTA”), aby sprawdzić, czy katalog (na przykład public_html) istnieje, jeśli istnieje cd do niego, a następnie wykonaj inny kod i zakończ; jeśli nie wykonasz kodu od razu i wyjdziesz?

Odpowiedz

9

możesz użyć listy. Przykład

import ftplib 
server="localhost" 
user="user" 
password="[email protected]" 
try: 
    ftp = ftplib.FTP(server)  
    ftp.login(user,password) 
except Exception,e: 
    print e 
else:  
    filelist = [] #to store all files 
    ftp.retrlines('LIST',filelist.append) # append to list 
    f=0 
    for f in filelist: 
     if "public_html" in f: 
      #do something 
      f=1 
    if f==0: 
     print "No public_html" 
     #do your processing here 
+0

To nie powie Ci, czy istnieje plik * (zamiast katalogu) o nazwie 'public_html'. –

+0

jeśli nie każdy ("public_html" w F f in listy plików): druku "No public_html" else: # coś zrobić czyli public = [f do f in listy plików jeśli "public_html" w F] jeśli nie publiczny: print „nie public_html” else: dla f publicznie: # Zrób coś – hughdbrown

+7

Zamiast polecenia wysyłając „list”, która zwraca linię pełnej informacji na temat każdego pliku, a następnie testowanie „, jeśli nazwa pliku in f ', możesz wysłać polecenie "NLST", które po prostu zwraca nazwę pliku dla każdego pliku. Zobacz http://docs.python.org/library/ftplib.html#ftplib.FTP.retrlines –

3

przykłady dołączone do odpowiedzi ghostdog74 mają trochę bug: lista wrócisz jest cała linia odpowiedzi, więc masz coś takiego

drwxrwxrwx 4 5063  5063   4096 Sep 13 20:00 resized 

Oznacza to, jeśli nazwa katalogu jest podobna do "50" (co jest w moim przypadku), otrzymasz fałszywy alarm. I zmodyfikowany kod na obsłużenie tego:

def directory_exists_here(self, directory_name): 
    filelist = [] 
    self.ftp.retrlines('LIST',filelist.append) 
    for f in filelist: 
     if f.split()[-1] == directory_name: 
      return True 
    return False 

nb, to jest wewnątrz klasy otoki FTP pisałem i self.ftp jest rzeczywiste połączenie FTP.

1

Tom ma rację, ale nikt go nie głosował , ale dla satysfakcji, który głosował na ghostdog74 będę mieszał i pisał ten kod, działa dla mnie, powinien pracować dla was.

import ftplib 
server="localhost" 
user="user" 
uploadToDir="public_html" 
password="[email protected]" 
try: 
    ftp = ftplib.FTP(server)  
    ftp.login(user,password) 
except Exception,e: 
    print e 
else:  
    filelist = [] #to store all files 
    ftp.retrlines('NLST',filelist.append) # append to list 
    num=0 
    for f in filelist: 
     if f.split()[-1] == uploadToDir: 
      #do something 
      num=1 
    if num==0: 
     print "No public_html" 
     #do your processing here 

przede wszystkim jeśli zastosujesz metodę pies duch, nawet jeśli powiesz katalogu „public” w f, nawet gdy go nie robi istnieć będzie oceniać true ponieważ społeczeństwo słowo istnieje w „public_html” tak to gdzie Tom, jeśli warunek może być użyty , więc zmieniłem go na , jeśli f.split() [- 1] == uploadToDir:.

Także jeśli wpiszesz nazwę katalogu somethig że nie robi istnieją, ale niektóre pliki i folder istnieje drugi przez ghostdog74 nie wykona, bo jej nigdy 0 jako zastąpione przez F w pętli więc użyłem num zmienna zamiast f i voila dobroć następuje ...

Vinay i Jonathon mają rację co do tego, co skomentowali.

15

Nslt wyświetli tablicę dla wszystkich plików na serwerze ftp. Sprawdź, czy jest tam nazwa twojego folderu.

from ftplib import FTP 
ftp = FTP('yourserver') 
ftp.login('username', 'password') 

folderName = 'yourFolderName' 
if folderName in ftp.nlst(): 
    #do needed task 
+1

Jest to niewiarygodne, ponieważ NLST nie rozróżnia plików i katalogów: daje tylko listę "nazw". –

+1

może on również chce znaleźć katalogi? – Temere

+0

Zwróć uwagę, że zwraca listę nazw plików i katalogów - nie ścieżek, więc otrzymasz 'usr' i' bin', ale *** nie *** '/ usr/bin' – Mawg

1

Metoda 3.x nlst() jest przestarzała. Użyj tego kodu:

import ftplib 

remote = ftplib.FTP('example.com') 
remote.login() 

if 'foo' in [name for name, data in list(remote.mlsd())]: 
    # do your stuff 

list() rozmowa jest potrzebna ponieważ mlsd() zwraca generator i nie obsługują sprawdzanie tego, co jest w nich (nie mają __contains__() metody).

Można zawinąć kompilację listy [name for name, data in list(remote.mlsd())] w funkcji metody i wywołać ją, gdy trzeba po prostu sprawdzić, czy istnieje katalog (lub plik).

4

Możesz wysłać "ścieżkę MLST" przez połączenie sterujące. Że wróci linię tym typu ścieżki (Zawiadomienie 'type = dir' na dole):

250-Listing "/home/user": 
modify=20131113091701;perm=el;size=4096;type=dir;unique=813gc0004;/
250 End MLST. 

Przetłumaczone na pytona, że ​​powinno być coś wzdłuż tych linii:

import ftplib 
ftp = ftplib.FTP() 
ftp.connect('ftp.somedomain.com', 21) 
ftp.login() 
resp = ftp.sendcmd('MLST pathname') 
if 'type=dir;' in resp: 
    # it should be a directory 
    pass 

Oczywiście powyższy kod nie jest w 100% niezawodny i wymagałby "prawdziwego" parsera. Możesz zajrzeć do implementacji polecenia MLSD w ftplib.py, która jest bardzo podobna (MLSD różni się od MLST tym, że odpowiedź wysłana przez połączenie , ale format przesyłanych linii jest taka sama): http://hg.python.org/cpython/file/8af2dc11464f/Lib/ftplib.py#l577

+0

Uaktualniam to, bo to jest wydaje się dobrym sposobem na zrobienie tego. Niestety, mój konkretny host zwraca "500 Nieznane polecenie", więc zastrzeżenie FTPor – Mawg

1

=> Znalazłem tę stronę podczas googlowania, aby sprawdzić, czy plik istnieje za pomocą ftplib w pythonie. Oto, co wymyśliłem (mam nadzieję, że komuś pomaga):

=> Podczas próby wyświetlenia nieistniejących plików/katalogów, ftplib zgłasza wyjątek. Mimo że Dodanie bloku try/except jest standardową praktyką i dobrym pomysłem, wolałbym, aby moje skrypty FTP pobierały plik (y) tylko po upewnieniu się, że istnieją. Pomaga to w uproszczeniu moich skryptów - przynajmniej wtedy, gdy możliwe jest umieszczenie katalogu na serwerze FTP.

Na przykład serwer FTP Edgar ma wiele plików przechowywanych w katalogu/edgar/daily-index /. Każdy plik ma nazwę "master.YYYYMMDD.idx". Nie ma gwarancji, że plik będzie istniał dla każdej daty (RRRRMMDD) - nie ma pliku z dnia 24 listopada 2013 r., Ale jest plik z dnia: 22 listopada 2013 r. Jak działa listing w tych dwóch przypadkach?

# Code 
from __future__ import print_function 
import ftplib 

ftp_client = ftplib.FTP("ftp.sec.gov", "anonymous", "[email protected]") 
resp = ftp_client.sendcmd("MLST /edgar/daily-index/master.20131122.idx") 
print(resp) 
resp = ftp_client.sendcmd("MLST /edgar/daily-index/master.20131124.idx") 
print(resp) 

# Output 
250-Start of list for /edgar/daily-index/master.20131122.idx 
modify=20131123030124;perm=adfr;size=301580;type=file;unique=11UAEAA398; 
UNIX.group=1;UNIX.mode=0644;UNIX.owner=1019; 
/edgar/daily-index/master.20131122.idx 
250 End of list 

Traceback (most recent call last): 
File "", line 10, in <module> 
resp = ftp_client.sendcmd("MLST /edgar/daily-index/master.20131124.idx") 
File "lib/python2.7/ftplib.py", line 244, in sendcmd 
return self.getresp() 
File "lib/python2.7/ftplib.py", line 219, in getresp 
raise error_perm, resp 
ftplib.error_perm: 550 '/edgar/daily-index/master.20131124.idx' cannot be listed 

Zgodnie z oczekiwaniami lista nieistniejącego pliku generuje wyjątek.

=> Ponieważ wiem, że serwer Edgar FTP będą mogli cieszyć się katalog/Edgar/dobę-index /, mój skrypt można wykonać następujące czynności, aby uniknąć podnoszenia wyjątki powodu nieistniejących plików:
a) Wykaz ten informator.
b) pobierz wymagane pliki, jeśli są one obecne na tej liście - Aby sprawdzić wykaz, zwykle wykonuję wyszukiwanie wyrażenia regularnego, na liście ciągów, które zwraca operacja aukcji.

Na przykład ten skrypt próbuje pobrać pliki z ostatnich trzech dni. Jeśli plik zostanie znaleziony dla określonej daty, zostanie pobrany, w przeciwnym razie nic się nie stanie.

import ftplib 
import re 
from datetime import date, timedelta 

ftp_client = ftplib.FTP("ftp.sec.gov", "anonymous", "[email protected]") 
listing = [] 
# List the directory and store each directory entry as a string in an array 
ftp_client.retrlines("LIST /edgar/daily-index", listing.append) 
# go back 1,2 and 3 days 
for diff in [1,2,3]: 
    today = (date.today() - timedelta(days=diff)).strftime("%Y%m%d") 
    month = (date.today() - timedelta(days=diff)).strftime("%Y_%m") 
    # the absolute path of the file we want to download - if it indeed exists 
    file_path = "/edgar/daily-index/master.%(date)s.idx" % { "date": today } 
    # create a regex to match the file's name 
    pattern = re.compile("master.%(date)s.idx" % { "date": today }) 
    # filter out elements from the listing that match the pattern 
    found = filter(lambda x: re.search(pattern, x) != None, listing) 
    if(len(found) > 0): 
    ftp_client.retrbinary(
     "RETR %(file_path)s" % { "file_path": file_path }, 
     open(
     './edgar/daily-index/%(month)s/master.%(date)s.idx' % { 
      "date": today 
     }, 'wb' 
    ).write 
    ) 

=> Interesujące są sytuacje, w których nie można wyświetlić katalogu na serwerze FTP. Na przykład edgarowy serwer FTP nie zezwala na edycję/edgar/data, ponieważ zawiera zbyt wiele podkatalogów. W takich przypadkach nie byłbym w stanie zastosować opisanej tutaj metody "Lista i sprawdzanie istnienia" - w takich przypadkach musiałbym użyć obsługi wyjątków w moim skrypcie downloadera, aby odzyskać nieistniejące próby dostępu do plików/katalogów.

Powiązane problemy