2015-07-16 39 views
5

Jak wykonać os.walk przejść przez drzewo katalogów bazy danych FTP (znajdujące się na serwerze zdalnym)? Sposób, w jaki kod jest skonstruowany teraz jest przewidziane (komentarze):Rozszerzanie funkcji os.walk Pythona na serwerze FTP

import fnmatch, os, ftplib 

def find(pattern, startdir=os.curdir): #find function taking variables for both desired file and the starting directory 
    for (thisDir, subsHere, filesHere) in os.walk(startdir): #each of the variables change as the directory tree is walked 
     for name in subsHere + filesHere: #going through all of the files and subdirectories 
      if fnmatch.fnmatch(name, pattern): #if the name of one of the files or subs is the same as the inputted name 
       fullpath = os.path.join(thisDir, name) #fullpath equals the concatenation of the directory and the name 
       yield fullpath #return fullpath but anew each time 

def findlist(pattern, startdir = os.curdir, dosort=False): 
    matches = list(find(pattern, startdir)) #find with arguments pattern and startdir put into a list data structure 
    if dosort: matches.sort() #isn't dosort automatically False? Is this statement any different from the same thing but with a line in between 
    return matches 

#def ftp(
#specifying where to search. 

if __name__ == '__main__': 
    import sys 
    namepattern, startdir = sys.argv[1], sys.argv[2] 
    for name in find(namepattern, startdir): print (name) 

myślę, że trzeba zdefiniować nową funkcję (tj def ftp()), aby dodać tę funkcjonalność do kodu powyżej. Obawiam się jednak, że funkcja os.walk domyślnie będzie tylko chodzić po drzewach katalogów komputera, z którego uruchamiany jest kod.

Czy istnieje sposób, w jaki mogę rozszerzyć funkcjonalność os.walk, aby móc przechodzić przez zdalne drzewo katalogów (przez FTP)?

+0

https: // PyPI .python.org/pypi/ftptool/0.5.1 –

+0

Próbuję unikać jakichkolwiek interfejsów poza 'ftplib'. Czy to się da zrobić? Zastrzeżenie: Próbowałem już 'ftptool' i nie mogłem zrobić tego, czego chcę. W związku z powyższym powyższy kod jest ponownym uruchomieniem w języku Python polecenia 'find' systemu Linux. Próbuję rozszerzyć go poprzez włączenie przełącznika FTP do 'os.walk'. – warship

+0

Jeśli ktoś może mi pokazać, jak ponownie zaimplementować to w 'ftptool' w sposób, który działa dla zdalnych baz danych FTP, przyjmuję to również jako odpowiedź. – warship

Odpowiedz

1

Wszystko, czego potrzebujesz, to wykorzystanie modułu Pythona ftplib. Ponieważ kod os.walk() opiera się na algorytmie przeszukiwania wszerz, trzeba znaleźć katalogi i nazwy plików w każdej iteracji, a następnie kontynuować rekursywne przechodzenie z pierwszego katalogu. Zaimplementowałem this algorithm około 2 lata temu za użycie jako serca FTPwalker, co jest optymalnym pakietem do przechodzenia przez wyjątkowo duże drzewa katalogów za pośrednictwem FTP.

from os import path as ospath 


class FTPWalk: 
    """ 
    This class is contain corresponding functions for traversing the FTP 
    servers using BFS algorithm. 
    """ 
    def __init__(self, connection): 
     self.connection = connection 

    def listdir(self, _path): 
     """ 
     return files and directory names within a path (directory) 
     """ 

     file_list, dirs, nondirs = [], [], [] 
     try: 
      self.connection.cwd(_path) 
     except Exception as exp: 
      print ("the current path is : ", self.connection.pwd(), exp.__str__(),_path) 
      return [], [] 
     else: 
      self.connection.retrlines('LIST', lambda x: file_list.append(x.split())) 
      for info in file_list: 
       ls_type, name = info[0], info[-1] 
       if ls_type.startswith('d'): 
        dirs.append(name) 
       else: 
        nondirs.append(name) 
      return dirs, nondirs 

    def walk(self, path='/'): 
     """ 
     Walk through FTP server's directory tree, based on a BFS algorithm. 
     """ 
     dirs, nondirs = self.listdir(path) 
     yield path, dirs, nondirs 
     for name in dirs: 
      path = ospath.join(path, name) 
      yield from self.walk(path) 
      # In python2 use: 
      # for path, dirs, nondirs in self.walk(path): 
      #  yield path, dirs, nondirs 
      self.connection.cwd('..') 
      path = ospath.dirname(path) 

teraz za pomocą tej klasy, można po prostu utworzyć obiekt połączenia przy użyciu modułu ftplib i przekazać obiekt obiekt do FTPWalk i tylko pętlę nad walk() funkcję:

In [2]: from test import FTPWalk 

In [3]: import ftplib 

In [4]: connection = ftplib.FTP("ftp.uniprot.org") 

In [5]: connection.login() 
Out[5]: '230 Login successful.' 

In [6]: ftpwalk = FTPWalk(connection) 

In [7]: for i in ftpwalk.walk(): 
      print(i) 
    ...:  
('/', ['pub'], []) 
('/pub', ['databases'], ['robots.txt']) 
('/pub/databases', ['uniprot'], []) 
('/pub/databases/uniprot', ['current_release', 'previous_releases'], ['LICENSE', 'current_release/README', 'current_release/knowledgebase/complete', 'previous_releases/', 'current_release/relnotes.txt', 'current_release/uniref']) 
('/pub/databases/uniprot/current_release', ['decoy', 'knowledgebase', 'rdf', 'uniparc', 'uniref'], ['README', 'RELEASE.metalink', 'changes.html', 'news.html', 'relnotes.txt']) 
... 
... 
... 
0

Im zamiar założyć to, co chcesz ... chociaż tak naprawdę nie mam pojęcia

ssh = paramiko.SSHClient() 
ssh.connect(server, username=username, password=password) 
ssh_stdin, ssh_stdout, ssh_stderr = ssh.exec_command("locate my_file.txt") 
print ssh_stdout 

będzie to wymagało serwera zdalnego mieć pakiet mlocate `sudo apt-get install mlocate; sudo updatedb();

+0

Niektóre bazy danych, z którymi się łączę, mają ten błąd: 'paramiko.ssh_exception.S SHException: Serwer 'ftp.server.org' nie został znaleziony w known_hosts'. Czy to znaczy, że nie mogę ssh do nich używając paramiko? Spróbuję zastosować podejście "mlocate" i opublikuję aktualizację. – warship

+1

@warship To oczywiste, że takie błędy występują w takim protokole. Istotą SSH jest bezpieczne połączenie. – Kasramvd