filecmp
简述
Python2.3以上的版本默认自带了filecmp模块,无需额外安装。我们可以用这个模块来检查原式与目标文件的一致性,
filecmp可以实现文件、目录、遍历子目录的差异对比功能。
代码路径:
https://github.com/python/cpython/blob/2.7/Lib/filecmp.py
https://github.com/python/cpython/blob/3.7/Lib/filecmp.py
接口
Classes:
dircmp //文件夹比较
Functions:
cmp(f1, f2, shallow=1) -> int //单文件比较
cmpfiles(a, b, common) -> ([], [], []) //多文件比较
clear_cache() //python3版本,清理缓存
实例
#本实例比较a、b两个文件夹,输出相同的、变化的、新增的、删除的文件名。
from filecmp import dircmp
import logging
import os
def walk_dir(dir_in, files_out):
for root, _, files in os.walk(dir_in, followlinks=True):
for f in files:
file_out = os.path.join(root, f)
files_out.append(file_out)
def get_diff_files(dcmp, same_items, change_items, add_items, del_items):
# 获取相同的文件
for name in dcmp.same_files:
same_fn = os.path.join(dcmp.left, name)
same_items.append(same_fn)
# 获取变化的文件
for name in dcmp.diff_files:
change_fn = os.path.join(dcmp.left, name)
change_items.append(change_fn)
# 获取新增的文件
left_only = dcmp.left_only
if left_only:
for name in left_only:
left_fn = os.path.join(dcmp.left, name)
if os.path.isdir(left_fn):
walk_dir(left_fn, add_items)
add_items.append(left_fn)
# 获取删除的文件
right_only = dcmp.right_only
if right_only:
for name in dcmp.right_only:
right_fn = os.path.join(dcmp.right, name)
if os.path.isdir(right_fn):
walk_dir(right_fn, del_items)
del_items.append(right_fn)
# 递归获取子文件夹的变化情况
for sub_dcmp in dcmp.subdirs.values():
get_diff_files(sub_dcmp, same_items, change_items, add_items, del_items)
def main():
src_dri = "/a/"
dst_dir = "/b/"
ignore_files = ['RCS', 'CVS', 'tags']
dcmp = dircmp(src_dir, dst_dir, ignore_files)
get_diff_files(dcmp, same_items, change_items, add_items, del_items)
if not diff_items and not del_items:
logging.info('no diff files')
logging.info('========run stop========
')
else:
logging.info('same items:%s' % pprint.pformat(same_items))
logging.info('change items:%s' % pprint.pformat(change_items))
logging.info('add items:%s' % pprint.pformat(add_items))
logging.info('del items:%s' % pprint.pformat(del_items))
if __name__ == '__main__':
main()
注意事项
1.dircmp使用的文件比较函数为:先比较文件stat(mode/size/mtime),不能确定再比较文件内容,
所以如果b中文件是a文件的复制,需要保证两个文件的mode/size/mtime相同,
但shutil.copy2中虽然复制了这几个参数,但由于mtime的精度不够用来表示纳秒级别的数据,
所以需要特别注意,解决方案有两种:
1) 两个文件都设置成1个相同的时间,比如1024,或者当前时间(只要保证在16位的范围能表示的值即可);
os.utime(src, (1024, 1024))
os.utime(dst, (1024, 1024))
2) python3支持纳秒级别的接口,所以可以直接使用
os.utime(dst, ns = (os.stat(src).st_ctime_ns, os.stat(src).st_mtime_ns));
2.python3版本的dircmp比较文件时会默认使用上次比较的缓存,所以如果要比较结果特别准确,无延时,需要调用clear_cache()。