[英]Python-FTP download all files in directory
我正在整理一個腳本,以通過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()
我敢打賭,您可以說運行時它並沒有太大作用,因此任何改進建議都將不勝感激。
我設法破解了這一點,所以現在為以后的訪問者發布一些相關的代碼:
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上有效。
如果這只是您要解決的問題,建議您使用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
函數的回調自己遍歷返回的文件。
看一下MLSD
或NLST
選項而不是LIST
,它們可能更易於解析。 (請注意,FTP實際上並未指定列表的外觀;它始終旨在由控制台上的人員來驅動,或者傳輸特定的文件名。因此,對FTP列表進行巧妙處理的程序例如將它們呈現給用戶。對於怪異或晦澀的服務器,GUI可能必須具有大量的特殊情況代碼。面對惡意文件名,它們可能都會做一些愚蠢的事情。)
可以改用sftp
嗎? sftp
確實有一個關於應該如何解析文件列表的規范,沒有明文傳輸用戶名/密碼,也沒有被動和主動連接的煩惱-它僅使用單個連接,這意味着與FTP相比,它可以跨更多的防火牆工作。
編輯 :您需要將一個'callable'對象傳遞給retrlines
函數。 可調用對象可以是定義__call__
方法的類的實例,也可以是函數。 雖然函數可能更易於描述,但類的實例可能更有用。 (您可以使用實例來收集文件名,但是該函數將必須寫入全局變量。錯誤。)
這是最簡單的可調用對象之一:
>>> 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
的對象調用iterlines
,然后在對象的lines
成員中查找詳細信息。
我認為這段代碼有點過大。
(來自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."
下載所有文件。
我是一個初學者,所以我沒有高效地編寫代碼,但是我編寫並測試了它是否正常工作。 這是我從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")
遞歸解決方案(py 2.7):
import os, ftplib, shutil, operator
def cloneFTP((addr, user, passw), remote, local):
try:
ftp = ftplib.FTP(addr)
ftp.login(user, passw)
ftp.cwd(remote)
except:
try: ftp.quit()
except: pass
print 'Invalid input ftp data!'
return False
try: shutil.rmtree(local)
except: pass
try: os.makedirs(local)
except: pass
dirs = []
for filename in ftp.nlst():
try:
ftp.size(filename)
ftp.retrbinary('RETR '+ filename, open(os.path.join(local, filename), 'wb').write)
except:
dirs.append(filename)
ftp.quit()
res = map(lambda d: cloneFTP((addr, user, passw), os.path.join(remote, d), os.path.join(local, d)), dirs)
return reduce(operator.iand, res, True)
可以使用Python程序調用dos腳本,而不是使用Python lib通過ftp下載目錄。 在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")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.