2011-03-08 161 views
23

Python newb在这里,请耐心等待。我把一个脚本放在一起,通过FTP下载目录中的所有文件。到目前为止,我已经成功地连接并读取一个文件,但我似乎无法使批量处理(获得从目录中的所有文件)这是我到目前为止有:Python-FTP下载目录中的所有文件

from ftplib import FTP 
import os, sys, os.path 

def handleDownload(block): 
    file.write(block) 
    print ".", 

ddir='C:\\Data\\test\\' 
os.chdir(ddir) 
ftp = FTP('test1/server/') 

print 'Logging in.' 
ftp.login('user1\\anon', 'pswrd20') 
directory = '\\data\\test\\' 

print 'Changing to ' + directory 
ftp.cwd(directory) 
ftp.retrlines('LIST') 

print 'Accessing files' 

for subdir, dirs, files in os.walk(directory): 
    for file in files: 
     full_fname = os.path.join(root, fname); 
     print 'Opening local file ' 
     ftp.retrbinary('RETR C:\\Data\\test\\' + fname, 
         handleDownload, 
         open(full_fname, 'wb')); 
     print 'Closing file ' + filename 
     file.close(); 
ftp.close() 

我敢打赌,你可以告诉它并没有做太多,当我运行它,所以任何改进建议,将不胜感激

PS这不是功课:DD

谢谢!

回答

7

如果这正是你想解决一个问题,我可能会建议wget命令:

cd c:\destination 
wget --mirror --continue --no-host-directories --user=username --password=s3cr3t ftp://hostname/source/path/ 

--continue选项可能是非常危险的,如果文件在服务器上的变化。如果文件只有,那么它非常友好。

但是,如果这是一个学习锻炼你,你想使你的程序的工作,我想你应该看这条线开始:

for subdir, dirs, files in os.walk(directory): 

directory一直远程源程序目录在你的大部分程序中,但是os.walk()函数不能走远程目录中的。您需要使用提供给retrlines函数的回调来遍历返回的文件。

看看MLSDNLST选项而不是LIST,它们可能会更容易解析。 (请注意,FTP实际上并未指定列表应如何显示;它始终打算由控制台上的人员驱动,或者传输特定的文件名。因此,使用FTP列表进行聪明处理的程序,例如将它们呈现给用户一个图形用户界面可能必须有大量的特殊情况代码,用于奇怪或者不明显的服务器,并且当面对恶意文件名时,他们可能都会做一些愚蠢的事情)。 sftp确实有一个关于如何解析文件列表的规范,不会在明文中传输用户名/密码,也没有被动与主动连接的巨大烦恼 - 它只是使用单连接,这意味着它可以在比FTP更多的防火墙上工作。

编辑:您需要将“可调用”对象传递给retrlines函数。可调用对象是定义方法的类的实例或函数。虽然该函数可能更容易描述,但类的实例可能更有用。 (您可以使用实例来收集文件名,但函数必须写入全局变量。)

这里的最简单的可调用对象之一:

>>> class c: 
... def __call__(self, *args): 
... print(args) 
... 
>>> f = c() 
>>> f('hello') 
('hello',) 
>>> f('hello', 'world') 
('hello', 'world') 

这将创建一个新的类,c,其限定了一实例方法__call__。这只是以相当愚蠢的方式打印它的参数,但它显示了我们谈论的是多么微不足道。 :)

如果你想要的东西更聪明,它可以做这样的事情:

class handle_lines: 
    def __init__(self): 
    self.lines = [] 
    def __call__(self, *args): 
    self.lines << args[0] 

呼叫iterlines这个类的一个对象,然后查看对象的详细信息lines成员。

+0

@Sosti,'在我的文章中提到的'retrlines'函数是一个超链接到文档:) – sarnold 2011-03-08 10:52:25

+0

非常感谢,他们都听起来像可靠的建议!我忘了在Windows XP上使用Python 2.5提到im(如果这很有用)如果我使用MLSD选项'ftp.retrlines('MLSD')',代码是否适用于迭代或需要修改更多? (确定它听起来有点愚蠢,但在这里新手,请记住?:DD) – Sosti 2011-03-08 11:00:21

+0

@Sosti,你仍然需要修改你的代码:你不能使用'os.walk()'函数。我将稍微编辑我的答案,以展示如何为'retrlines'创建回调对象。 – sarnold 2011-03-08 11:27:17

55

我已经成功地破解这个,所以现在发布的代码中的相关位为未来的用户:

filenames = ftp.nlst() # get filenames within the directory 
print filenames 

for filename in filenames: 
    local_filename = os.path.join('C:\\test\\', filename) 
    file = open(local_filename, 'wb') 
    ftp.retrbinary('RETR '+ filename, file.write) 

    file.close() 

ftp.quit() # This is the “polite” way to close a connection 

这为我工作在Python 2.5中,Windows XP中。

+8

filenames = ftp.nlst() – nad2000 2011-10-13 09:57:41

+2

推荐的方法是使用:'ftp.quit()'而不是'ftp.close()'。 请参阅此链接(https://docs.python.org/2/library/ftplib.html#ftplib.FTP.quit) – Oran 2014-07-06 11:36:42

-1

而不是使用Python的lib来下载一个目录,我们可以从python程序调用一个dos脚本。在dos脚本中,我们将使用本地ftp协议,该协议可以使用mget *.*从文件夹下载所有文件。

fetch.bat 
ftp -s:fetch.txt 

fetch.txt 
open <ipaddress> 
<userid> 
<password> 
bin (set the mnode to binary) 
cd </desired directory> 
mget *.* 
bye 

fetch.py 
import os 
os.system("fetch.bat") 
+4

这是比解决方案更多的解决方法 – m1k3y3 2012-09-27 16:29:16

+1

它也特定于windows(dos) – Carl 2016-08-11 22:28:09

+0

有时候,它有帮助。 – JOHN 2018-01-09 06:11:44

0

我是一个初学者,所以我没有有效地制作代码,但我做了它,并测试它工作。这是我从ftp站点下载文件和文件夹的过程,但文件结构的深度有限。

try: 
    a = input("Enter hostname : ") 
    b = input("Enter username : ") 
    c = input("Enter password : ") 
    from ftplib import FTP 
    import os 
    os.makedirs("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp") 
    os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp") 
    ftp = FTP(host = a, user= b, passwd = c) 
    D = ftp.nlst() 
    for d in D: 
     l = len(d) 
     char = False 
     for i in range(0,l): 
      char = char or d[i]=="." 
     if not char: 
     ftp.cwd("..") 
     ftp.cwd("..") 
     E = ftp.nlst("%s"%(d)) 
     ftp.cwd("%s"%(d)) 
     try: 
      os.makedirs("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s"%(d)) 
     except: 
      print("you can debug if you try some more") 
     finally: 
      os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s"%(d)) 
      for e in E: 
       l1 = len(e) 
       char1 = False 
       for i in range(0,l1): 
        char1 = char1 or e[i]=="." 
       if not char1: 
        ftp.cwd("..") 
        ftp.cwd("..") 
        F = ftp.nlst("%s/%s"%(d,e)) 
        ftp.cwd("%s/%s"%(d,e)) 
        try: 
         os.makedirs("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s\\%s"%(d,e)) 
        except: 
         print("you can debug if you try some more") 
        finally: 
         os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s\\%s"%(d,e)) 
         for f in F: 
          if "." in f[2:]: 
           with open(f,'wb') as filef: 
            ftp.retrbinary('RETR %s' %(f), filef.write) 
          elif not "." in f: 
           try: 
            os.makedirs("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s\\%s\\%s"%(d,e,f)) 
           except: 
            print("you can debug if you try some more") 
       elif "." in e[2:]: 
        os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp\\%s"%(d)) 
        ftp.cwd("..") 
        ftp.cwd("..") 
        ftp.cwd("..") 
        ftp.cwd("%s"%(d)) 
        with open(e,'wb') as filee: 
         ftp.retrbinary('RETR %s' %(e), filee.write) 
     elif "." in d[2:]: 
      ftp.cwd("..") 
      ftp.cwd("..") 
      os.chdir("C:\\Users\\PREM\\Desktop\\pyftp download\\ftp") 
      with open(d,'wb') as filed: 
      ftp.retrbinary('RETR %s'%(d), filed.write) 
    ftp.close() 
    print("Your files has been successfully downloaded and saved. Bye") 
except: 
    print("try again you can do it") 
finally: 
    print("code ran") 
+0

你能解释你的代码是如何工作的?这将使OP和其他人能够在其他地方了解和应用您的方法(如果适用)。仅有代码的答案[不鼓励](http://meta.stackexchange.com/q/148272/284827),并且可能被删除。 - [审查期间](http:// stackoverflow。com/review/late-answers/11704863) – 2016-03-20 18:25:00

+0

你的意思是代码? – PremVijay 2016-05-14 14:43:36

2

这个代码是有点矫枉过正,我认为。

(从Python的例子https://docs.python.org/2/library/ftplib.html)ftp.login后(),并设置ftp.cwd(),您可以只使用:

os.chdir(ddir) 
ls = ftp.nlst() 
count = len(ls) 
curr = 0 
print "found {} files".format(count) 
for fn in ls: 
    curr += 1 
    print 'Processing file {} ... {} of {} ...'.format(fn, curr, count) 
    ftp.retrbinary('RETR ' + fn, open(fn, 'wb').write) 

ftp.quit() 
print "download complete." 

下载的所有文件。