2009-07-08 16 views
13

Ich verwende dieses Skript zu verbinden FTP-Server und die Liste zu probieren verfügbare Verzeichnisse:Wie kann Python überprüfen, ob ein FTP-Verzeichnis existiert?

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() 

Wie verwende ich ftp.retrlines (‚LIST‘) Ausgabe zu überprüfen, ob Verzeichnis (zB public_html) vorhanden ist, wenn es existiert, cd zu ihm und dann etwas anderen Code ausführen und beenden; wenn nicht Code sofort ausführen und beenden?

Antwort

9

können Sie eine Liste verwenden. Beispiel

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

Dies sagt Ihnen nicht, ob es eine * Datei * (anstatt eines Verzeichnisses) namens 'public_html' gibt. –

+0

wenn nicht ("public_html" in f für f in Dateiliste): print "No public_html" anderes: # etwas tun oder: public = [f für f in Dateiliste, wenn "public_html" in f] wenn nicht öffentlich: print „No public_html“ anderes: für f in der Öffentlichkeit: # tun Sie etwas – hughdbrown

+7

Stattdessen Befehl „LIST“ zu senden, die eine Linie voller Informationen über jede Datei zurückgibt, und testet dann ‚, wenn Dateiname In f 'könnten Sie den Befehl "NLST" senden, der nur den Dateinamen für jede Datei zurückgibt. Siehe http://docs.python.org/library/ftplib.html#ftplib.FTP.retrlines –

3

Die Beispiele zu ghostdog74 Antwort angebracht haben ein bisschen ein Fehler: die Liste, die Sie zurückbekommen die ganze Linie der Antwort ist, so dass Sie so etwas wie

drwxrwxrwx 4 5063  5063   4096 Sep 13 20:00 resized 

bekommen Dies bedeutet, wenn Ihr Verzeichnisname ist etwas wie '50' (was in meinem Fall war), Sie erhalten einen falschen positiven. Ich änderte den Code zu handhaben:

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 

N. B., dies innerhalb einer FTP-Wrapper-Klasse, die ich schrieb und self.ftp ist die eigentliche FTP-Verbindung.

1

Tom ist korrekt, aber niemand hat ihn gewählt aber für die Zufriedenheit, die Ghostdog74 gewählt habe, werde ich diesen Code mischen und schreiben, funktioniert für mich, sollte für euch arbeiten.

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 

vor allem, wenn Sie Ghost Dog Methode folgen, auch wenn Sie sagen Verzeichnis „public“ in f, wenn es auch leider nicht vorhanden, es zu true ausgewertet wird, weil das Wort öffentlich in „public_html“ existiert, so das ist, wo Tom wenn Bedingung verwendet werden kann so änderte ich es zu wenn f.split() [- 1] == uploadToDir:.

Auch wenn Sie einen Verzeichnisnamen somethig eingeben, die doesnt existieren aber einige Dateien und Ordner existiert die zweite von ghostdog74 wird niemals ausgeführt werden, da seine nie 0, wie in for-Schleife von f außer Kraft gesetzt, so benutzte ich num Variable statt f und voila die Güte folgt ...

Vinay und Jonathon haben Recht, was sie kommentiert.

15

Nslt wird ein Array für alle Dateien im FTP-Server auflisten. Überprüfen Sie einfach, ob Ihr Ordnername dort ist.

+1

Dies ist unzuverlässig, da NLST nicht zwischen Dateien und Verzeichnissen unterscheidet: es gibt nur eine Liste von 'Namen'. –

+1

vielleicht will er auch Verzeichnisse finden? – Temere

+0

Beachten Sie, dass es eine Liste von Datei- und Verzeichnisnamen zurückgibt - keine Pfade, Sie erhalten also 'usr' und' bin', aber *** not *** '/ usr/bin' – Mawg

1

In 3.x nlst() Methode ist veraltet. Verwenden Sie diesen Code:

import ftplib 

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

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

Der list() Anruf benötigt wird, weil mlsd() einen Generator zurückgibt und sie unterstützen keine Kontrolle, was in ihnen ist (nicht über __contains__() Methode).

Sie können [name for name, data in list(remote.mlsd())] List Comp in einer Funktion der Methode und rufen Sie es, wenn Sie nur überprüfen müssen, ob ein Verzeichnis (oder eine Datei) vorhanden ist.

4

Sie können "MLST path" über die Steuerverbindung senden. dass eine Linie, einschließlich der Typ des Pfades (notice 'type = dir' hier unten) zurück:

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

Übersetzt in Python, die in dieser Richtung etwas sein sollte:

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 

Natürlich ist der obige Code nicht 100% zuverlässig und würde einen 'echten' Parser benötigen. Sie bei der Umsetzung von MLSD Befehl in ftplib.py, die sehr ähnlich ist, aussehen kann (MLSD unterscheidet sich von MLST, dass die Antwort in über die Daten gesendet Verbindung, aber das Format der Leitungen übertragen wird, ist das gleiche): http://hg.python.org/cpython/file/8af2dc11464f/Lib/ftplib.py#l577

+0

Ich stimme dem zu, weil es dies tut scheint ein guter Weg, es zu tun. Leider gibt mein spezieller Host "500 Unknown command" zurück, also schütze FTPor – Mawg

1

=> Ich habe diese Webseite beim googlen gefunden, um zu sehen, ob eine Datei mit ftplib in Python existiert. Folgendes habe ich herausgefunden (hoffe, es hilft jemandem):

=> Beim Versuch, nicht existierende Dateien/Verzeichnisse aufzulisten, löst ftplib eine Ausnahme aus. Auch wenn das Hinzufügen eines try/exception-Blocks eine gängige Praxis und eine gute Idee ist, würde ich es vorziehen, wenn meine FTP-Skripte die Datei (en) erst herunterladen, nachdem sie sich vergewissert haben, dass sie existieren. Dies hilft, meine Skripte einfacher zu halten - zumindest wenn ein Verzeichnis auf dem FTP-Server aufgelistet werden kann.

Zum Beispiel hat der Edgar FTP-Server mehrere Dateien, die unter dem Verzeichnis/edgar/daily-index/gespeichert sind. Jede Datei hat den Namen "master.YYYYMMDD.idx". Es gibt keine Garantie, dass eine Datei für jedes Datum existiert (JJJJMMTT) - es gibt keine Datei vom 24. November 2013, aber es gibt eine Datei vom 22. November 2013. Wie funktioniert das Listing in diesen beiden Fällen?

# 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 

Wie erwartet, wird beim Auflisten einer nicht vorhandenen Datei eine Ausnahme generiert.

=> Da ich, dass der Edgar FTP-Server kennen sicherlich das Verzeichnis haben/edgar/daily-Index/kann mein Skript tun das aufgrund nicht vorhandenen Dateien erhöhen Ausnahmen zu vermeiden, folgende:
a) Liste dieser Verzeichnis.
b) laden Sie die erforderlichen Datei (en) herunter, wenn sie in dieser Liste vorhanden sind - Um die Liste zu überprüfen, führe ich normalerweise eine regexp-Suche in der Liste der Zeichenfolgen durch, die der Auflistungsvorgang zurückgibt.

Zum Beispiel versucht dieses Skript, Dateien für die letzten drei Tage herunterzuladen. Wenn eine Datei für ein bestimmtes Datum gefunden wird, wird sie heruntergeladen, sonst passiert nichts.

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 
    ) 

=> Interessanterweise gibt es Situationen, in denen wir ein Verzeichnis auf dem FTP-Server nicht auflisten können. Der edgar FTP-Server zum Beispiel verbietet die Auflistung auf/edgar/data, weil er viel zu viele Unterverzeichnisse enthält. In solchen Fällen wäre ich nicht in der Lage, den hier beschriebenen Ansatz "Auflisten und Prüfen auf Vorhandensein" zu verwenden - in diesen Fällen müsste ich die Ausnahmebehandlung in meinem Downloader-Skript verwenden, um von nicht vorhandenen Datei-/Verzeichniszugriffsversuchen wiederherzustellen.

Verwandte Themen