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()

在这里插入图片描述

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