web-dev-qa-db-ja.com

Python ftpディレクトリが存在するかどうかを確認する方法は?

このスクリプトを使用して、サンプルの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 anonymous@
ftp.retrlines('LIST')     # list directory contents
ftp.quit()

Ftp.retrlines( 'LIST')出力を使用して、ディレクトリ(public_htmlなど)が存在するかどうかを確認し、そこにcdが存在するかどうかを確認してから、他のコードを実行して終了するにはどうすればよいですか。コードをすぐに実行して終了しない場合は?

15
Phil

Nsltは、ftpサーバー内のすべてのファイルの配列を一覧表示します。フォルダ名がそこにあるかどうかを確認してください。

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

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

リストを使用できます。例

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
11
ghostdog74

制御接続を介して「MLSTパス」を送信できます。これにより、パスのtypeを含む行が返されます(ここで 'type = dir'に注意してください)。

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

pythonに変換されます。これは、次のようになります。

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

もちろん、上記のコードは100%信頼できるわけではなく、「実際の」パーサーが必要になります。 ftplib.pyでのMLSDコマンドの実装を見ることができます。これは非常によく似ています(MLSDは、応答がdata接続を介して送信されるという点でMLSTとは異なりますただし、送信される行の形式は同じです): http://hg.python.org/cpython/file/8af2dc11464f/Lib/ftplib.py#l577

4

Ghostdog74の回答に添付されている例には、少しバグがあります。返されるリストは応答の全行であるため、次のようになります。

drwxrwxrwx    4 5063     5063         4096 Sep 13 20:00 resized

これは、ディレクトリ名が「50」(私の場合はそうだった)のようなものである場合、誤検知が発生することを意味します。これを処理するようにコードを変更しました。

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

注:これは私が作成したFTPラッパークラス内にあり、self.ftpは実際のFTP接続です。

3
Tom

トムは正しいですが、誰も彼に投票しませんでしたが、ghostdog74に投票した満足度のために、私はこのコードを混ぜて書きます。私のために働きます。

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

まず、ゴーストドッグ方式に従うと、fでディレクトリ「public」と言っても、存在しない場合でも、「public_html」にpublicという単語が存在するため、trueと評価されます。 f.split()[-1] == uploadToDir:に変更しました。

また、存在しないディレクトリ名somethigを入力したが、いくつかのファイルとフォルダが存在する場合、ghostdog74による2番目のディレクトリは、forループでfinによってオーバーライドされるため、0が実行されないため、numfの代わりに変数を使用すると、次のようになります。

VinayとJonathonは、彼らがコメントしたことについて正しいです。

1
user1176501

3.xでは、nlst()メソッドは非推奨になりました。このコードを使用します:

_import ftplib

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

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

list()はジェネレーターを返し、それらの中にあるもののチェックをサポートしていないため、mlsd()呼び出しが必要です(__contains__()メソッドがありません)。

[name for name, data in list(remote.mlsd())] list compをメソッドの関数でラップし、ディレクトリ(またはファイル)が存在するかどうかを確認する必要があるときに呼び出すことができます。

1
Marek Marecki

=> Pythonでftplibを使用してファイルが存在するかどうかを確認する方法をグーグルで検索しているときに、このWebページを見つけました。以下は私が理解したことです(それが誰かを助けることを願っています):

=>存在しないファイル/ディレクトリを一覧表示しようとすると、ftplibで例外が発生します。 try/exceptionブロックを追加することは標準的な方法であり、良い考えですが、FTPスクリプトは、ファイルが存在することを確認した後でのみダウンロードすることをお勧めします。これは、スクリプトを単純に保つのに役立ちます。少なくともFTPサーバーにディレクトリを一覧表示できる場合はそうです。

たとえば、Edgar FTPサーバーには、ディレクトリ/ edgar/daily-index /の下に保存されている複数のファイルがあります。各ファイルには、「master.YYYYMMDD.idx」という名前が付けられています。すべての日付(YYYYMMDD)にファイルが存在するという保証はありません。2013年11月24日付けのファイルはありませんが、2013年11月22日付けのファイルがあります。これら2つの場合、リストはどのように機能しますか?

# 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

予想どおり、存在しないファイルをリストすると例外が生成されます。

=> EdgarFTPサーバーには確かにディレクトリ/ edgar/daily-index /があることがわかっているので、スクリプトは次のことを実行して、存在しないファイルによる例外の発生を回避できます。
a)このディレクトリを一覧表示します。
b)必要なファイルがこのリストに存在する場合はダウンロードします-リストを確認するには、通常、リスト操作で返される文字列のリストに対して正規表現検索を実行します。

たとえば、このスクリプトは過去3日間のファイルのダウンロードを試みます。特定の日付のファイルが見つかった場合はダウンロードされ、それ以外の場合は何も起こりません。

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
    )

=>興味深いことに、FTPサーバー上のディレクトリを一覧表示できない場合があります。たとえば、edgar FTPサーバーは、サブディレクトリが多すぎるため、/ edgar/dataへのリストを許可しません。このような場合、ここで説明する「リストと存在の確認」アプローチを使用できません。これらの場合、存在しないファイル/ディレクトリアクセスの試行から回復するには、ダウンローダースクリプトで例外処理を使用する必要があります。

1
gautamc
from ftplib import FTP

ftp = FTP()
ftp.connect(hostname, 21) 
ftp.login(username,password)

try:
    ftp.cwd('your folder name')
    #do the code for successfull cd
except Exception:
    #do the code for folder not exists
0