歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

Python文件和目錄操作實例代碼

對於文件和目錄的處理,雖然可以通過操作系統命令來完成,但是Python語言為了便於開發人員以編程的方式處理相關工作,提供了許多處理文件和目錄的內置函數。重要的是,這些函數無論是在Unix、Windows還是Macintosh平台上,它們的使用方式是完全一致的。

本文將詳細解釋這些函數的使用方法。首先,介紹Python語言中類似於Windows系統的dir命令的列出文件功能,然後描述如何測試一個文件名對應的是一個標准文件、目錄還是鏈接,以及提取文件大小和日期的方法。之後,還將介紹如何刪除文件和目錄,如何復制和刪除文件,以及怎樣將一個完整的文件路徑分解成目錄部分和文件名部分,最後,講解目錄的創建,以及如何在目錄樹中移動目錄並處理文件。

一、顯示目錄內容
當想要列出當前目錄中所有擴展名為.jpg或.gif的文件時,就可以使用glob模塊來完成此項任務,如下所示:
import glob
filelist = glob.glob('*.jpg') + glob.glob('*.gif')
上述代碼使用了glob函數,該函數的參數為要顯示的文件類型。
在這裡,文件類型是通過類似UNIX操作系統shell風格通配符描述的一些文件名來指定的。
這些通配符的使用方法,具體請參考fnmatch模塊的文檔,那裡有具體的說明和示例。

為了顯示一個目錄中的全部文件,可以使用如下所示的os.listdir函數:
files = os.listdir(r'C:\hpl\scripting\src\py\intro') #適用於 Windows
files = os.listdir('/home/hpl/scripting/src/py/intro') # 適用於Unix
# 跨平台版本:
files = os.listdir(os.path.join(os.environ['scripting'],
'src', 'py', 'intro'))
files = os.listdir(os.curdir) # 當前目錄中的所有文件
files = glob.glob('*') + glob.glob('.*')

二、測試文件類型
知道,文件名、目錄名和鏈接名都是用一個字符串作為其標識符的,但是給一個標識符,該如何確定它所指的到底是常規文件文件名、目錄名還是鏈接名呢?這時,可以使用os.path模塊提供的isfile函數、isdir函數和islink函數來達成目標,如下所示:
print myfile, '是一個',
if os.path.isfile(myfile):
print 'plain file'
if os.path.isdir(myfile):
print 'directory'
if os.path.islink(myfile):
print 'link'

您還可以查找文件的日期及其大小:
time_of_last_access = os.path.getatime(myfile)
time_of_last_modification = os.path.getmtime(myfile)
size = os.path.getsize(myfile)

這裡的時間以秒為單位,並且從1970年1月1日開始算起。
為了獲取以天為單位的最後訪問日期,可以使用下列代碼:
import time # time.time()返回當前時間
age_in_days = (time.time()-time_of_last_access)/(60*60*24)
為了獲取文件的詳細信息,可以使用os.stat函數和stat模塊中的其它實用程序來達到目的,如下:
import stat
myfile_stat = os.stat(myfile)
size = myfile_stat[stat.ST_SIZE]
mode = myfile_stat[stat.ST_MODE]
if stat.S_ISREG(mode):
print '%(myfile)是一個常規文件,大小為 %(size)d 字節' %\
vars()

有關stat模塊的詳細信息,請參見Python Library Reference。若想測試一個文件的讀、寫以及執行權限,可以用os.access函數,具體如下所示:
if os.access(myfile, os.W_OK):
print myfile, '具有寫權限'
if os.access(myfile, os.R_OK | os.W_OK | os.X_OK):
print myfile, '具有讀、寫以及執行權限'
像上面這樣的測試代碼,對CGI腳本來說非常有用。

三、文件和目錄的刪除 (腳本學堂 www.linuxidc.com 編輯整理)
若要刪除單個文件的話,可以使用os.remove函數,例如:os.remove('mydata.dat')。Os.remove的別名是os.unlink,不過後者跟傳統的UNIX操作系統以及Perl中清除文件的函數重名。可以使用下列方式來刪除一組文件,如所有以.jpg以及*.gif為擴展名的文件:
for file in glob.glob('*.jpg') + glob.glob('*.gif'):
os.remove(file)

只有當目錄中內容已經被清空時,才可以使用rmdir命令來刪除該目錄。不過,經常想要刪除一個含有許多文件的目錄樹,這時可以使用shutil模塊提供的rmtree函數,如下所示:
shutil.rmtree('mydir')
它相當於UNIX操作系統中的命令rm -rf mydir。
可以建立一個自定義函數,使其在進行刪除操作時將文件和目錄做同等對待,其典型用法如下所示:
remove('my.dat') #刪除當個文件my.dat
remove('mytree') #刪除單個目錄樹 mytree
# 通過字符串列表中的名稱來刪除多個文件/目錄樹:
remove(glob.glob('*.tmp') + glob.glob('*.temp'))
remove(['my.dat','mydir','yourdir'] + glob.glob('*.data'))
下面是remove函數的實現:
def remove(files):
"""刪除一個或多個文件和/或目錄。"""
if isinstance(files, str): # files是個字符串嗎?
files = [files] # 把files從字符串轉為列表
if not isinstance(files, list): # files不是列表嗎?

for file in files:
if os.path.isdir(file):
shutil.rmtree(file)
elif os.path.isfile(file):
os.remove(file)

測試下remove函數的靈活性:
# 建立10個目錄tmp_* ,以及10各文件tmp__*:
for i in range(10):
os.mkdir('tmp_'+str(i))
f = open('tmp__'+str(i), 'w'); f.close()
remove('tmp_1') # tmp_1為目錄
remove(glob.glob('tmp_[0-9]') + glob.glob('tmp__[0-9]'))

作為上述remove函數實現的一個注記,進行了下列測試:
if not isinstance(files, list):
它實際上是過於嚴厲。需要的只是一個被遍歷的一個文件/目錄名序列。實際上,並不關心名稱是否存儲在一個列表、元組或者數值數組中,所以更好的測試應該像下面這樣:
if not operator.isSequenceType(files):

四、文件的復制與重命名
當要復制文件時,可以使用shutil模塊:
import shutil
shutil.copy(myfile, tmpfile)
#拷貝最後訪問時間和最後修改時間:
shutil.copy2(myfile, tmpfile)
# 拷貝一個目錄樹:
shutil.copytree(root_of_tree, destination_dir, True)
Copytree的第三個參數規定對符號鏈接的處理,其中True表示保留符號鏈接;而False則意味著使用文件的物理副本替代符號鏈接。
Python語言能夠很好地支持路徑名的跨平台組成:Os.path.join能使用正確的分界符(在UNIX和Mac OS X操作系統中使用/,在 Windows 上使用\)來聯接目錄和文件名,變量os.curdir和os.pardir分別表示當前工作目錄及其父目錄。 像下面的UNIX操作系統命令
cp http://www.linuxidc.com/f1.c .

可以使用Python語言提供一個跨平台的實現:
shutil.copy(os.path.join(os.pardir,os.pardir,'f1.c'), os.curdir)
Os模塊中的rename函數通常被用於重命名一個文件:
os.rename(myfile, 'tmp.1') # 將myfile重命名為'tmp.1'

這個函數也可用來在相同的文件系統之內移動文件。這裡,將myfile移動到目錄d下面:
os.rename(myfile, os.path.join(d, myfile))
在跨文件系統移動文件時,可以先使用shutil.copy2來復制文件,然後再刪除原來的副本即可,如下:
shutil.copy2(myfile, os.path.join(d, myfile))
os.remove(myfile)
後面這種移動文件的方法是最安全的。

五、分解路徑名
假設使用變量fname來存放一個包含完整路徑的文件名,例如:
/usr/home/hpl/scripting/python/intro/hw.py
有時候,需要將這樣的文件路徑拆分為基本名稱hw.py和目錄名/usr/home/hpl/scripting/python/intro。在Python語言中,可以使用下列代碼達到目的:
basename = os.path.basename(fname)
dirname = os.path.dirname(fname)
# 或
dirname, basename = os.path.split(fname)
擴展名是通過os.path.splitext函數提取出來的,
root, extension = os.path.splitext(fname)
這樣,fname中的擴展名部分即.py被賦給變量extension,而其余部分則賦給了變量root。(http://www.linuxidc.com)如果想得到不帶點號的擴展名的話,只需使用os.path.splitext(fname)[1][1:]即可。
假設一個文件名為f,其擴展名隨意,若想將其擴展名改為ext,可以使用下面的代碼:
newfile = os.path.splitext(f)[0] + ext
下面是一個具體的示例:
>>> f = '/some/path/case2.data_source'
>>> moviefile = os.path.basename(os.path.splitext(f)[0] + '.mpg')
>>> moviefile
'case2.mpg'

六、目錄的創建和移動
Os模塊中的函數mkdir可以用來創建目錄,而chdir函數則可以移動目錄,如下:
origdir = os.getcwd() # 將當前位置記下來
newdir = os.path.join(os.pardir, 'mynewdir')
if not os.path.isdir(newdir):
os.mkdir(newdir) # 或者os.mkdir(newdir,'0755')
os.chdir(newdir)
...
os.chdir(origdir) # 返回原目錄
os.chdir(os.environ['HOME']) # 移到主目錄
假設想要在自己的主目錄下創建一個新目錄py/src/test1,但是目前py、src和test1都不存在。如果使用mkdir命令來創建的話,需要使用三次才能建好這個嵌套的目錄,但是使用Python語言提供的os.makedirs命令的話,則無需這樣麻煩了,該命令可以一次建好整個目錄:
os.makedirs(os.path.join(os.environ['HOME'],'py','src','test1'))

七、遍歷目錄樹
下面的函數調用
os.path.walk(root, myfunc, arg)
將遍歷root目錄樹;然後,對每個目錄名dirname分別調用myfunc(arg, dirname, files)即可,這裡參數files是dir中的文件名列表(可通過調用os.listdir(dirname)來獲得);arg是用戶從調用代碼中傳遞來的參數。對於UNIX操作系統用戶來說,Python語言中跨平台的os.path.walk相當於Unix命令find。
在解釋os.path.walk的用法時,人們常使用寫出主目錄中所有子目錄內的文件的名稱為例進行說明。當然,也可以在一個交互式的Python命令行中使用下列代碼段來體會os.path.walk的使用:
def ls(arg, dirname, files):
print dirname, 'has the files', files
os.path.walk(os.environ['HOME'], ls, None)
本例中,參數arg並非必需,所以在os.path.walk調用中讓其取值為None即可。
為了列出主目錄中所有大於1Mb的文件,可以使用下面的代碼:
def checksize1(arg, dirname, files):
for file in files:
filepath = os.path.join(dirname, file)
if os.path.isfile(filepath):
size = os.path.getsize(filepath)
if size > 1000000:
size_in_Mb = size/1000000.0
arg.append((size_in_Mb, filename))
bigfiles = []
root = os.environ['HOME']
os.path.walk(root, checksize1, bigfiles)
for size, name in bigfiles:
print name, '大小為', size, 'Mb'

現在,使用arg來建立一個數據結構,這裡是一個2元組構成的列表,其中每個2元組存放文件的尺寸(以MB為單位)和完整的文件路徑。如果用於所有目錄的函數調用中都要更改arg的話,那麼arg必須是一個可變的數據結構,即允許適當地進行修改。
參數dirname是當前正在訪問的目錄的絕對路徑,而參數files內的文件名則是相對於dirname的相對路徑。在此期間,當前工作目錄並沒有改變,那就是說該腳本仍然呆在腳本啟動時刻所在的目錄中。這就是為什麼需要把filepath弄成帶有dirname和file的絕對路徑的原因。若要改變當前工作目錄為dirname,只要在針對每個目錄調用os.path.walk的函數中調用一下os.chdir(dirname),然後在該函數的末尾重新調用os.chdir(dirname)將當前工作目錄改回原值即可,如下所示:
def somefunc(arg, dirname, files):
origdir = os.getcwd(); os.chdir(dirname)

os.chdir(origdir)
os.path.walk(root, somefunc, arg)
當然,如果您願意也可以編寫具有類似功能的代碼來替代os.path.walk。下面的代碼,將針對每個文件而非每個目錄來調用的自定義函數,如下所示:
def find(func, rootdir, arg=None):
# 對rootdir目錄中的每個文件調用func
files = os.listdir(rootdir) # 獲取rootdir目錄中的所有文件
files.sort(lambda a, b: cmp(a.lower(), b.lower()))
for file in files:
fullpath = os.path.join(rootdir, file)
if os.path.islink(fullpath):
pass
elif os.path.isdir(fullpath):
find(func, fullpath, arg)
elif os.path.isfile(fullpath):
func(fullpath, arg)
else:
print 'find: cannot treat ', fullpath
上面的函數find可以從scitools模塊中獲取。與內置函數os.path.walk相反,的find函數以大小寫敏感的字母順序來訪問文件和目錄。
可以使用find函數來列出所有大於1Mb的文件:
def checksize2(fullpath, bigfiles):
size = os.path.getsize(fullpath)
if size > 1000000:
bigfiles.append('%.2fMb %s' % (size/1000000.0, fullpath))
bigfiles = []
root = os.environ['HOME']
find(checksize2, root, bigfiles)
for fileinfo in bigfiles:
print fileinfo
參數arg帶來了巨大的靈活性。可以使用它來同時存放輸入數據和生成的數據結構。下一個范例將收集所有大於一定尺寸的帶有規定擴展名的文件的文件名和大小。輸出的結果按照文件大小排列。
bigfiles = {'filelist': [], # 文件名和大小列表
'extensions': ('.*ps', '.tiff', '.bmp'),
'size_limit': 1000000, # 1 Mb
}
find(checksize3, os.environ['HOME'], bigfiles)
def checksize3(fullpath, arg):
treat_file = False
ext = os.path.splitext(fullpath)[1]
import fnmatch # Unix的shell風格的通配符匹配
for s in arg['extensions']:
if fnmatch.fnmatch(ext, s):
treat_file = True # fullpath帶有正確的擴展名
size = os.path.getsize(fullpath)
if treat_file and size > arg['size_limit']:
size = '%.2fMb' % (size/1000000.0) # 打印
arg['filelist'].append({'size': size, 'name': fullpath})
# 按照大小排列文件
def filesort(a, b):
return cmp(float(a['size'][:-2]), float(b['size'][:-2]))
bigfiles['filelist'].sort(filesort)
bigfiles['filelist'].reverse()
for fileinfo in bigfiles['filelist']:
print fileinfo['name'], fileinfo['size']
注意為列表排序的函數,bigfiles['filelist']函數中的每個元素就是一個字典,鍵size保存著一個字符串,不過在進行比較之前必須將單位Mb(最後兩個字符)去掉,並將其轉換為浮點數。

八、小結
對於文件和目錄的處理,雖然可以通過操作系統命令來完成,但是Python語言為了便於開發人員以編程的方式處理相關工作,提供了許多處理文件和目錄的內置函數。重要的是,這些函數無論是在Unix、Windows還是Macintosh平台上,它們的使用方式是完全一致的。本文詳細解釋了這些函數的使用方法,其中,首先介紹了顯示目錄內容的功能,然後描述如何測試一個文件名對應的是一個標准文件、目錄還是鏈接,以及提取文件大小和日期的方法。之後,還將介紹如何刪除文件和目錄,如何復制和刪除文件,以及怎樣將一個完整的文件路徑分解成目錄部分和文件名部分,最後,講解目錄的創建,以及如何在目錄樹中移動目錄並處理文件。

Python解析xml文檔實例  http://www.linuxidc.com/Linux/2012-02/54760.htm

《Python核心編程 第二版》.(Wesley J. Chun ).[高清PDF中文版] http://www.linuxidc.com/Linux/2013-06/85425.htm

《Python開發技術詳解》.( 周偉,宗傑).[高清PDF掃描版+隨書視頻+代碼] http://www.linuxidc.com/Linux/2013-11/92693.htm

Python腳本獲取Linux系統信息 http://www.linuxidc.com/Linux/2013-08/88531.htm

在Ubuntu下用Python搭建桌面算法交易研究環境 http://www.linuxidc.com/Linux/2013-11/92534.htm

Python 語言的發展簡史 http://www.linuxidc.com/Linux/2014-09/107206.htm

Python 的詳細介紹:請點這裡
Python 的下載地址:請點這裡

Copyright © Linux教程網 All Rights Reserved