一、高級文件處理接口shutil
shutil
是一種高層次的文件操作工具
類似於高級API,而且主要強大之處在於其對文件的複製與刪除操作更是比較支持好。
使用方法
- copyfile( src, dst) 從源src複製到dst中去。當然前提是目標地址是具備可寫權限。拋出的異常信息爲IOException. 如果當前的dst已存在的話就會被覆蓋掉
- copymode( src, dst) 只是會複製其權限其他的東西是不會被複制的
- copystat( src, dst) 複製權限、最後訪問時間、最後修改時間
- copy( src, dst) 複製一個文件到一個文件或一個目錄
- copy2( src, dst) 在copy上的基礎上再複製文件最後訪問時間與修改時間也複製過來了,類似於cp –p的東西
- copy2( src, dst) 如果兩個位置的文件系統是一樣的話相當於是rename操作,只是改名;如果是不在相同的文件系統的話就是做move操作
- copytree(olddir,newdir,True/Flase) 把olddir拷貝一份newdir,如果第3個參數是True,則複製目錄時將保持文件夾下的符號連接,如果第3個參數是False,則將在複製的目錄下生成物理副本來替代符號連接
[root@python ~]# mkdir /tmp/demo
[root@python ~]# cd /tmp/demo/
[root@python demo]# mkdir -p dir1
[root@python demo]# touch a.txt b.txt c.txt
[root@python demo]# touch sh.py cc.py 001.jpg 002.jpg 003.jpg
//創建所需文件
[root@python demo]# ipython
//打開ipython
也可以在PyCharm中創建文件,進行實施。
1、複製文件和文件夾
shutil.copy(file1,file2) #文件
shutil.copytree(dir1,dir2) #文件夾
(1)複製文件
In [1]: import shutil
In [2]: shutil.copy('a.txt','aa.txt')
Out[2]: 'aa.txt'
//可在PyCharm和Linux的相應路徑查看是否有生成的文件
In [3]: ls
001.jpg 003.jpg a.txt cc.py sh.py
002.jpg aa.txt b.txt c.txt
(2)複製文件夾
In [5]: shutil.copytree('dir1','dir11')
Out[5]: 'dir11'
In [6]: ls
001.jpg 003.jpg a.txt cc.py dir1/ sh.py
002.jpg aa.txt b.txt c.txt dir11/
(3)將文件內容拷貝到另一個文件中
# _*_ coding:utf-8 _*_
__author__ = 'junxi'
import shutil
# 將文件內容拷貝到另一個文件中
shutil.copyfileobj(open('old.txt', 'r'), open('new.txt', 'w'))
# 拷貝文件
shutil.copyfile('old.txt', 'old1.txt')
# 僅拷貝權限。內容、組、用戶均不變
shutil.copymode('old.txt', 'old1.txt')
# 複製權限、最後訪問時間、最後修改時間
shutil.copystat('old.txt', 'old1.txt')
# 複製一個文件到一個文件或一個目錄
shutil.copy('old.txt', 'old2.txt')
# 在copy上的基礎上再複製文件最後訪問時間與修改時間也複製過來了
shutil.copy2('old.txt', 'old2.txt')
# 把olddir拷貝一份newdir,如果第3個參數是True,則複製目錄時將保持文件夾下的符號連接,如果第3個參數是False,則將在複製的目錄下生成物理副本來替代符號連接
shutil.copytree('C:/Users/xiaoxinsoso/Desktop/aaa', 'C:/Users/xiaoxinsoso/Desktop/bbb')
# 移動目錄或文件
shutil.move('C:/Users/xiaoxinsoso/Desktop/aaa', 'C:/Users/xiaoxinsoso/Desktop/bbb') # 把aaa目錄移動到bbb目錄下
# 刪除一個目錄
shutil.rmtree('C:/Users/xiaoxinsoso/Desktop/bbb') # 刪除bbb目錄
2、文件和文件夾的重命名與移動
shutil.move(filel, file2)
shutil.move(file, dir)
(1)文件的重命名
In [7]: shutil.move('aa.txt','dd.txt')
Out[7]: 'dd.txt'
In [8]: ls
001.jpg 003.jpg b.txt c.txt dir1/ sh.py
002.jpg a.txt cc.py dd.txt dir11/
(2)文件移動到文件夾
In [9]: shutil.move('dd.txt','dir1')
Out[9]: 'dir1/dd.txt'
In [11]: ls dir1
dd.txt
3、刪除目錄
shutil.rmtree(dir) # 刪除目錄
os.unlink(file) # 刪除文件
刪除目錄
In [15]: shutil.rmtree('dir1')
In [16]: ls
001.jpg 003.jpg b.txt c.txt sh.py
002.jpg a.txt cc.py dir11/
二、文件內容管理
1、目錄和文件的對比
filecmp模塊包含了比較目錄和文件的操作。
filecmp可以實現文件,目錄,遍歷子目錄的差異對比功能。
自帶filecmp模塊,無需安裝。
(1)目錄結構
目錄dir1中文件a_copy.txt,a.txt,c.txt內容一樣,b.txt內容不一樣
[root@python demo]# mkdir compare
[root@python demo]# cd compare/
[root@python compare]# mkdir -p dir1 dir2
[root@python compare]# mkdir dir1/subdir1
[root@python compare]# ls
dir1 dir2
[root@python compare]# touch dir1/a_copy.txt dir1/a.txt dir1/b.txt dir1/c.txt
[root@python compare]# touch dir2/a.txt dir2/b.txt dir2/c.txt
[root@python compare]# mkdir -p dir2/subdir1 dir2/subdir2
[root@python compare]# touch dir2/subdir1/sb.txt
//創建所需文件
[root@python compare]# ipython
//打開ipython
filecmp提供3個操作方法,cmp(單文件對比),cmpfile(多文件對比),dircmp(目錄對比)。
(2)示例代碼:
使用filecmp模塊的cmp函數比較兩個文件是否相同,如果文件相同則返回True,否則False
In [1]: import filecmp
In [2]: filecmp.cmp('a.txt','b.txt')
Out[2]: False
In [3]: filecmp.cmp('a.txt','c.txt')
Out[3]: True
In [4]: filecmp.cmp('a.txt','a_copy.txt')
Out[4]: True
(3)比較兩個文件
filecmp目錄下還有一個名爲cmpfiles的函數, 該函數用來同時比較兩個不同的目錄下的多個文件,並且返回一個三元組,分別包含相同的文件、不同的文件和無法比較的文件。示例如下:
In [9]: filecmp.cmpfiles('dir1','dir2',['a.txt','b.txt','c.txt','a_copy.txt'])
Out[9]: (['b.txt'], ['a.txt', 'c.txt'], ['a_copy.txt'])
# 返回一個三元組第一個是一樣的第個是不一樣的第三個是無法比較(沒有這個文件或者其他原因)
(4)比較多個文件
cmpfiles函數同時用來比較兩個目錄下的文件,也可以使用該函數比較兩個目錄。但是,在比較兩個目錄時,需要通過參數指定可能的文件,因此比較繁瑣。
filecmp中還有一個名爲dircmp的函數,用來比較兩個目錄。調用dircmp函數以後,會返回一個dircmp類的對象,該對象保存了諸多屬性,我們可以通過查看這些屬性獲取目錄之間的差異。如下所示:
In [11]: d = filecmp.dircmp('dir1','dir2')
#設置測試目錄
In [12]: d.report()
diff dir1 dir2
Only in dir1 : ['a_copy.txt']
Only in dir2 : ['subdir2']
Identical files : ['b.txt']
Differing files : ['a.txt', 'c.txt']
Common subdirectories: ['subdir1']
(5)直接比較目錄不指定文件
目錄對比,通過filecmp(a,b[,ignore[,hide]])
類創建一個目錄比較對象用於比較文件夾,通過該類比較兩個文件夾,可以獲取一些詳細的比較結果(如只在A文件夾存在的文件列表),並支持子文件夾的遞歸比較。
In [17]: d.left_list #查看dir1目錄結構
Out[17]: ['a.txt', 'a_copy.txt', 'b.txt', 'c.txt', 'subdir1']
In [18]: d.right_list #查看dir2目錄結構
Out[18]: ['a.txt', 'b.txt', 'c.txt', 'subdir1', 'subdir2']
In [19]: d.left_only #僅第dir1目錄存在的
Out[19]: ['a_copy.txt']
In [20]: d.right_only #僅第dir2目錄存在的
Out[20]: ['subdir2']
2、MD5校驗和比較
校驗碼是通過散列函數計算而成,是一種從任何數據中創建小的數字”指紋”的方法。散列函數把消息或數據壓縮成摘要,使得數據量變小,便於進行比較。MDS是目前使用最官方的
MD5哈希一般用於檢查文件的完整性,尤其常用於檢查文件傳輸、磁盤錯誤或其他情況下文件的正確性。
Linux下計算一個文件的MD5校驗碼,如下所示:
[root@192 demo]# md5sum a.txt
d41d8cd98f00b204e9800998ecf8427e a.txt
在Python中計算文件的MD5校驗碼也非常簡單,使用標準庫hashlib模塊即可。如下所示:
import hashlib
d = hashlib.md5()
with open('b.txt') as f:
for line in f:
d.update(line.encode('utf-8'))
print(d.hexdigest())
# 或者可以這樣(最常見的寫法,常用於圖片的命名)
>>> import hashlib
>>> hashlib.md5(b'123').hexdigest()
'202cb962ac59075b964b07152d234b70'
# 也可以使用hash.new()這個一般方法,hashlib.new(name[, data]),name傳入的是哈希加密算法的名稱,如md5
>>> hashlib.new('md5', b'123').hexdigest()
'202cb962ac59075b964b07152d234b70'
記得創建b.txt文件
三、Python管理壓縮包
1、tarfile
既然有壓縮模塊zipfile,那有一個歸檔模塊tarfile也是很自然的。tarfile模塊用於解包和打包文件,包括被gzip
,bz2
或lzma
壓縮後的打包文件。如果是.zip
類型的文件,建議使用zipfile模塊,更高級的功能請使用shutil模塊。
定義的類和異常
tarfile.open(name=None, mode='r', fileobj=None, bufsize=10240, \kwargs)
返回一個TarFile類型的對象。本質上就是打開一個文件對象。Python隨處可見這種文件對象類型的設計,你很容易就明白,不是嗎?
name
是文件名或路徑。
bufsize
用於指定數據塊的大小,默認爲20*512字節。
mode
是打開模式,一個類似filemode[:compression]
格式的字符串,可以有下表所示的組合,默認爲“r”
模式 | 說明 |
---|---|
'r'or'r:*' | 自動解壓並打開文件(推薦模式) |
'r:' | 只打開文件不解壓 |
'r:gz' | 採用gzip格式解壓並打開文件 |
'r:bz2' | 採用bz2格式解壓並打開文件 |
'r:xz' | 採用lzma格式解壓並打開文件 |
'x'or'x:' | 僅創建打包文件,不壓縮 |
'x:gz' | 採用gzip方式壓縮並打包文件 |
'x:bz2' | 採用bzip2方式壓縮並打包文件 |
'x:xz' | 採用lzma方式壓縮並打包文件 |
'a'or'a:' | 打開文件,並以不壓縮的方式追加內容。如果文件不存在,則新建 |
'w'or'w:' | 以不壓縮的方式寫入 |
'w:gz' | 以gzip的方式壓縮並寫入 |
'w:bz2' | 以bzip2的方式壓縮並寫入 |
'w:xz' | 以lzma的方式壓縮並寫入 |
注意 |
不支持'a:gz', 'a:bz2'和'a:xz'的模式 |
如果當前模式不能正常打開文件用於讀取,將拋出ReadError
異常,這種情況下,請使用“r”模式。如果指定的壓縮方式不支持,將拋出CompressionError
異常。
在w:gz
,r:gz
,w:bz2
,r:bz2
,x:gz
,x:bz2
模式下,tarfile.open()
方法額外接受一個壓縮等級參數compresslevel
,默認值爲9。
(1)讀取文件
壓縮文件提取碼:0418
import tarfile
with tarfile.open('tengine-2.3.2.tar.gz') as t:
# getmember() 查看文件列表
for member in t.getmembers():
print(member.name)
with tarfile.open('tengine-2.3.2.tar.gz') as t:
t.extractall('a','tengine-2.3.2/man')
t.extract('tengine-2.3.2/man','b')
常用方法說明:
- getmembers () : 獲取tar包中的文件列表
- member.name : 獲取tar包中文件的文件名
- extract(member, path) : 提取單個文件
- extractall(path,memebers) : 提取所有的文件
(2)創建tar包
記得創建read.txt文件
import tarfile
with tarfile.open( 'readme.tar',mode='w') as out :
out.add('read.txt')
可在對應位置查看是否有readme.tar文件
(3)讀取與創建壓縮包
import tarfile
with tarfile.open('tarfile_add.tar ',mode='r:gz') as out:
pass
with tarfile.open('tarfile_add.tar ',mode='r:bz2') as out:
pass
(4)備份指定文件到壓縮包中
import os
import fnmatch
import tarfile
import datetime
def is_file_math(filename, patterns):
'''查找特定類型的文件'''
for pattern in patterns:
if fnmatch.fnmatch(filename, pattern):
return True
return False
def find_files(root, patterns=['*']):
for root, dirnames, filenames in os.walk(root):
for filename in filenames:
if is_file_math(filename, patterns):
yield os.path.join(root, filename)
patterns = ['*.txt','*.md']
now = datetime.datetime.now().strftime('%Y_%m_%d_%H_%M_%S')
filename = 'backup_all_file_{0}.tar.gz'.format(now)
with tarfile.open(filename, 'w') as f:
for item in find_files('.', patterns):
f.add(item)
可在對應位置查看是否有readme.tar文件
2、zipfile
zipfile 是python裏用來做zip格式編碼的壓縮和解壓縮的,由於是很常見的zip格式,所以這個模塊使用頻率也是比較高。
zipfile裏有兩個非常重要的class, 分別是ZipFile和ZipInfo, 在絕大多數的情況下,只需要使用這兩個class就可以。
- ZipFile是主要的類,用來創建和讀取zip文件;
- ZipInfo是存儲的zip文件的每個文件的信息的。
(1)讀取zip文件
import zipfile
demo_zip = zipfile.ZipFile('read.zip')
print(demo_zip.namelist())
demo_zip.extractall('1')
demo_zip.extract('a.jpg','2')
//記得創建名爲2的目錄,當然第一個字段的路徑也必須正確。
常用方法說明:
- namelist() :返回zip文件中包含的所有文件和文件夾的字符串列表
- extract(filename, path): 從zip文件中提取單個文件
- extractall(path): 從zip文件中提取所有文件
(2)創建zip文件
import zipfile
newZip = zipfile.ZipFile( 'new.zip', mode='w' )
newZip.write('a.jpg') #文件必須存在
newZip.close()
(3) Python命令行調用zipfile
#創建zip文件
python -m zipfile -c new1.zip b.txt
#查看zip文件內容
python -m zipfile -l new1.zip
File Name Modified Size
b.txt 2020-04-26 14:35:12 0
#提取zip文件到指定目錄
python -m zipfile -e new1.zip /
zipfile模塊提供的命令行接口包含的選項:
- -1: 顯示zi p格式壓縮包中的文件列表
- -e: 提取z i p格式的壓縮包
- -c:創建zip格式的壓縮包
- -t: 驗證文件是不是一個有效的zi p格式壓縮包
(4) zipfile的各個屬性
import zipfile, os
zipFile = zipfile.ZipFile(os.path.join(os.getcwd(), 'duoduo.zip'))
zipInfo = zipFile.getinfo('文件中的文件.txt')
print ('filename:', zipInfo.filename) #獲取文件名稱
print ('date_time:', zipInfo.date_time) #獲取文件最後修改時間。返回一個包含6個元素的元組:(年, 月, 日, 時, 分, 秒)
print ('compress_type:', zipInfo.compress_type) #壓縮類型
print ('comment:', zipInfo.comment) #文檔說明
print ('extra:', zipInfo.extra) #擴展項數據
print ('create_system:', zipInfo.create_system) #獲取創建該zip文檔的系統。
print ('create_version:', zipInfo.create_version) #獲取 創建zip文檔的PKZIP版本。
print ('extract_version:', zipInfo.extract_version) #獲取 解壓zip文檔所需的PKZIP版本。
print ('extract_version:', zipInfo.reserved) # 預留字段,當前實現總是返回0。
print ('flag_bits:', zipInfo.flag_bits) #zip標誌位。
print ('volume:', zipInfo.volume) # 文件頭的卷標。
print ('internal_attr:', zipInfo.internal_attr) #內部屬性。
print ('external_attr:', zipInfo.external_attr) #外部屬性。
print ('header_offset:', zipInfo.header_offset) # 文件頭偏移位。
print ('CRC:', zipInfo.CRC) # 未壓縮文件的CRC-32。
print ('compress_size:', zipInfo.compress_size) #獲取壓縮後的大小。
print ('file_size:', zipInfo.file_size) #獲取未壓縮的文件大小。
zipFile.close() #
3、shutil創建和讀取壓縮包
shutil可以簡單地理解爲sh + util
,shell工具的意思。shutil模塊是對os模塊的補充,主要針對文件的拷貝、刪除、移動、壓縮和解壓操作。
使用方法
- copyfile( src, dst) 從源src複製到dst中去。當然前提是目標地址是具備可寫權限。拋出的異常信息爲IOException. 如果當前的dst已存在的話就會被覆蓋掉
- copymode( src, dst) 只是會複製其權限其他的東西是不會被複制的
- copystat( src, dst) 複製權限、最後訪問時間、最後修改時間
- copy( src, dst) 複製一個文件到一個文件或一個目錄
- copy2( src, dst) 在copy上的基礎上再複製文件最後訪問時間與修改時間也複製過來了,類似於cp –p的東西
- copy2( src, dst) 如果兩個位置的文件系統是一樣的話相當於是rename操作,只是改名;如果是不在相同的文件系統的話就是做move操作
- copytree(olddir,newdir,True/Flase) 把olddir拷貝一份newdir,如果第3個參數是True,則複製目錄時將保持文件夾下的符號連接,如果第3個參數是False,則將在複製的目錄下生成物理副本來替代符號連接
測試
import shutil
print(shutil.get_archive_formats())
輸出結果如下:
[('bztar', "bzip2'ed tar-file"), ('gztar', "gzip'ed tar-file"), ('tar', 'uncompressed tar file'), ('xztar', "xz'ed tar-file"), ('zip', 'ZIP file')]
(1)創建壓縮包
import shutil
# 參數1:生成的壓縮包文件名
# 參數2:壓縮包的格式
# 參數3:壓縮的目錄
shutil.make_archive('a.jpg','gztar', 'ddd')
可在對應位置查看是否有生成的文件
(2)解壓
import shutil
# 參數1:需要解壓的壓縮包
# 參數2:解壓的目錄
print(shutil.unpack_archive('a.jpg.tar.gz','jpg'))
可在對應位置查看是否有生成的文件