python 文件與文件路徑管理

python文件與文件路徑管理

python標準庫的os模塊包含與操作系統的系統環境、文件系統、用戶數據庫以及權限進行交互的函數。
Linux下的路徑分隔符是"/",Windows下的路徑分割符是"\"。

os.path進行路徑和文件管理

getcwd 獲取當前目錄
import os
os.getcwd()
#輸出如下
#轉到當前目錄D:\project\bianzu下
os.listdir('.')
#['email_bianzu.py', 'email_bianzu_win.py', 'email_test1.py']
split 返回一個二元組,包含文件的路徑與文件名
import os
path = r"D:\project\bianzu\email_bianzu.py"
print(os.path.split(path))
#輸出如下所示:
('D:\\project\\bianzu', 'email_bianzu.py')
dirname 返回文件的路徑
path = r"D:\project\bianzu\email_bianzu.py"
print(os.path.dirname(path))
#輸出如下所示:
D:\project\bianzu
返回文件的文件名
path = r"D:\project\bianzu\email_bianzu.py"
print(os.path.basename(path))
#輸出如下所示:
email_bianzu.py

得到文件或路徑的絕對路徑

path = r"D:\project\bianzu\email_bianzu.py"
print(os.path.abspath('.'))
#輸出如下所示:
D:\project\bianzu
join 根據不同的操作系統平臺,使用不同的路徑分割符拼接路徑
print(os.path.join("D:\project","test","bianzu.py"))
# 輸出結果如下所示
D:\project\test\bianzu.py

判斷文件類型

os.path模塊也提供了若干函數用來判斷路徑是否存在,以及路徑所指文件的類型

1 exists 參數path所指向的路徑是否存在
2 isfile 參數path所指向的路徑存在,並且是一個文件
3 isdir 參數path所指向的路徑存在,並且是一個文件夾

使用os模塊管理文件和目錄

os模塊包含的文件和目錄操作函數,包括創建目錄、刪除目錄、刪除文件、重命名文件等
1 unlink/remove: 刪除path路徑所指向的文件
2 rmdir: 刪除path路徑指向的文件夾,該文件夾必須爲空,否則會報錯
3 mkdir:創建一個文件夾
4 rename: 重命名文件或文件夾

os.remove("1.jpg")
os.rmdir("dir1")
os.mkdir(r"/home/bianzu/tmp/")
os.rename("mydir","newdir")

os模塊包含了修改文件權限、判斷文件權限的函數

os提供了三個常量來表示讀、寫、可執行權限,即R_OK、W_OK和X_OK
1 chmod用來修改文件的權限
1 access用來判斷文件是否具有相應的權限

示例:通過命令行讀取文件名稱,先判斷文件是否存在,如果文件不存在,則直接退出。然後判斷文件是否具有讀權限,如果沒有讀權限,將文件賦予所有用戶都具有讀寫執行權限。如果文件存在並且已經具有讀權限,讀取文件內容

import sys
import os

def main():
    filename = sys.argv[1]
    print(filename)
    if not os.path.isfile(filename):
        raise SystemExit(filename + ' does not exists')
    elif not os.access(filename,os.R_OK):
        os.chmod(filename, 777)
    else:
        with open(filename) as f:
            print(f.read())

if __name__ == "__main__":
    main()

高級文件處理接口shutil

os模塊是對操作系統的接口進行封裝,主要作用是跨平臺。shutil模塊包含複製、移動、重命名和刪除文件及目錄的函數,主要作用是管理文件和目錄。

複製文件和文件夾

copy用來拷貝一個文件,copytree用來拷貝一個目錄

import shutil
shutil.copy('a.py','b.py')
shutil.copytree('dir1','dir2')

文件和文件夾的移動與改名

shutil模塊中的move(src,dst)用來將路徑src處的文件移動到dst處,並返回新位置的絕對路徑。dst是一個目錄,則將文件移動到目錄之中。dst是一個文件名稱,則將文件移動到目標目錄下,並重命名爲dst

import shutil
shutil.move("a.py","b.py")
shutil.move("a.py","dir1")

刪除目錄

刪除文件,可以使用os模塊的remove和unlink函數,刪除目錄,可以使用os模塊的rmdir和removedirs函數。但rmdir和removedirs都要求被刪除的目錄非空不能進行強制刪除,shutil.rmtree不管目錄是否非空,都直接刪除整個目錄。

# 刪除目錄
shutil.rmtree("/home/bianzu/tmp/")
# 再建立目錄
os.mkdir(r"/home/bianzu/tmp/")

文件內容管理

filecmp模塊包含了比較目錄和文件的操作。

cmp函數

cmp函數用來比較兩個文件是否相同,如果文件相同,返回True,否則返回False

import filecmp
filecmp.cmp('a.txt','b.txt')
False
cmpfiles

cmpfiles函數用來同時比較兩個不同目錄下的多個文件,並且返回一個三元組,分別包含相同的文件、不同的文件和無法比較的文件

import filecmp
filecmp.cmpfiles('dir1','dir2',['a.txt','b.txt','a_copy.txt'])
#輸出如下所示:
(['a.txt'],['b.txt'],['a_copy.txt'])
dircmp函數

dircmp函數用來比較兩個目錄,會返回一個dircmp類的對象,該對象保存了諸多屬性

import filecmp
d=filecmp.dircmp(r"D:\tmp\test",r"D:\tmp\test1")
d.report()

# 輸出如下所示
diff D:\tmp\test D:\tmp\test1
Only in D:\tmp\test : ['test2.txt']
Only in D:\tmp\test1 : ['a.txt', 'data.txt']
Identical files : ['test3.txt', 'test4.txt']

filecmp模塊的dircmp函數僅僅比較目錄下面的文件和子目錄,不會遞歸比較目錄內容。

MD5校驗和比較

通過校驗碼的方式對文件進行比較。校驗碼是通過散列函數計算而成,是一種從任何數據中創建小的數字指紋方法。散列函數把消息或數據壓縮成摘要,使得數據量變小,便於進行比較。MD5是目前使用最廣泛的散列算法。
MD5哈希一般用於檢查文件完整性,尤其常用於檢測文件傳輸、磁盤錯誤或其他情況下文件的正確性。

在linux下計算文件的MD5校驗碼,只需要以文件名爲參數調用md5sum命令即可。

md5sum test.txt
fad5096b8f92d0e906a87dce2e371471  test.txt

在python中計算文件的MD5校驗碼使用標準庫中的hashlib模塊即可。

import hashlib
d =hashlib.md5()
with open('D:/tmp/a.txt') as f:
    for line in f:
        d.update(line.encode('utf-8'))
        print(line)
print(d.hexdigest())

# 輸出如下所示
hi,happy everyday
3add452390c4bfaf7692a4fece6e108c

完整案例:找到目錄下的重複文件

首先通過find_specific_files函數找到目錄下的所有文件,通過MD5校驗碼判斷文件是否相同。將計算文件的MD5校驗碼的功能封裝成一個名爲get_file_checksum函數,該函數接受文件名作爲參數,返回文件的MD5校驗功能。

#-*- coding: UTF-8 -*-
import os
import fnmatch
import hashlib
import sys

CHUNK_SIZE = 8192

def is_file_match(filename,patterns):
    for pattern in patterns:
        if fnmatch.filter(filename,pattern):
            return True
    return False


# 查找目錄下所有文件,指定pattern的話,則是查找符合patterns的文件

def find_specific_files(root,patterns=['*'],exclude_dirs = []):
    for root,dirnames,filenames in os.walk(root):
        for exclude_dir in exclude_dirs:
            if exclude_dir in dirnames:
                dirnames.remove(exclude_dir)
        for filename in filenames:
            if is_file_match(filename,patterns):
                yield os.path.join(root,filename)


def get_chunk(filename):
    #UnicodeDecodeError: 'gbk' codec can't decode byte 0xff in position 0: illegal multibyte sequence
    #遇到有些編碼不規範的文件,遇到UnicodeDecodeError,因爲在文本文件中可能夾雜了一些非法編碼的字符。遇到這種情況,open()函數還接收一個errors參數,
    # 表示如果遇到編碼錯誤後如何處理。最簡單的方式是直接忽略:
    with open(filename,errors='ignore') as f:
        while True:
            chunk = f.read(CHUNK_SIZE)
            if not chunk:
                break
            else:
                yield chunk

def get_file_checksum(filename):
    h = hashlib.md5()
    for chunk in get_chunk(filename):
        #出現這個報錯TypeError: Unicode-objects must be encoded before hashing
        #是因爲python3中字符對象是unicode對象,不能直接加密
        h.update(chunk.encode("utf-8"))
    return h.hexdigest()

def main():
    sys.argv.append("")
    directory = sys.argv[1]
    if not os.path.isdir(directory):
        raise SystemExit(f"{directory} is not a directory")

    record = {}

    for item in find_specific_files(directory):
        checksum = get_file_checksum(item)
        if checksum in record:
            print(f"find duplicate file: {record[checksum]} vs {item}")
        else:
            record[checksum] = item

if __name__ == '__main__':
    main()

在這裏插入圖片描述

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