python處理文件和文件的方法(shutil,filecmp ,MD5,tarfile,zip)

一、高級文件處理接口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)目錄結構

python處理文件和文件的方法(shutil,filecmp ,MD5,tarfile,zip)

目錄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模塊用於解包和打包文件,包括被gzipbz2lzma壓縮後的打包文件。如果是.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'))

可在對應位置查看是否有生成的文件

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章