11. 文件和目录访问

这个模块提供了代表文件系统路径的类,其语义适用于不同的操作系统。

文件类继承图

../_images/pathlib-inheritance.png

11.1. pathlib

11.1.1. 基本使用

# 列出目录下的所有文件
In [1]: from pathlib import Path

In [2]: p=Path(".")

In [3]: [ x for x in p.iterdir() if x.is_dir() ]
Out[3]:
[WindowsPath('.vscode'),
WindowsPath('node_modules'),
WindowsPath('public'),
WindowsPath('scaffolds'),
WindowsPath('source'),
WindowsPath('themes'),
WindowsPath('tmp')]

# 所有特定的文件,glob使用通配功能,递归需要**
In [7]: list(p.glob("**/*.rst"))
Out[7]:
WindowsPath('source/_posts/CA服务器的搭建.rst'),
WindowsPath('source/_posts/mariadb多实例的三种实现.rst'),

# 导航目录
In [14]: p = Path('/etc')

In [15]: p
Out[15]: WindowsPath('/etc')

In [16]: q = p / 'init.d' / 'reboot'

In [17]: q
Out[17]: WindowsPath('/etc/init.d/reboot')

# 基础文件判断
In [20]: q.exists()
Out[20]: False

In [21]: q.is_dir()
Out[21]: False

In [22]: q.is_file()
Out[22]: False

11.1.2. pure路径

# 路径整合
In [24]: from pathlib import PurePath

In [25]: PurePath('foo', 'some/path', 'bar')
Out[25]: PureWindowsPath('foo/some/path/bar')

In [26]: str(PurePath('foo', 'some/path', 'bar'))
Out[26]: 'foo\\some\\path\\bar'

In [33]: os.fspath(PurePath('foo', 'some/path', 'bar'))
Out[33]: 'foo\\some\\path\\bar'

# 路径判断,window是不区分大小写的,linux区分大小写(更准确的说应该是文件系统)
In [28]: from pathlib import *

In [29]:  PurePosixPath('foo') == PurePosixPath('FOO')
Out[29]: False

In [30]: PureWindowsPath('foo') == PureWindowsPath('FOO')
Out[30]: True

# 文件系统路径
In [32]: import os

In [33]: os.fspath(PurePath('foo', 'some/path', 'bar'))
Out[33]: 'foo\\some\\path\\bar'

# 路径拆分
In [37]: p=PureWindowsPath('c:/Program Files/')

In [38]: p.parts
Out[38]: ('c:\\', 'Program Files')

# 驱动盘
In [39]: p.drive
Out[39]: 'c:'

# 根
In [40]: p.root
Out[40]: '\\'

# 锚定
In [41]: p.anchor
Out[41]: 'c:\\'

#父目录
In [42]: p.parents
Out[42]: <PureWindowsPath.parents>

In [43]: p.parents[0]
Out[43]: PureWindowsPath('c:/')

# 文件名
In [46]: p.name
Out[46]: 'Program Files'

# 没有扩展的名字a.tar 得到a
In [47]: p.stem
Out[47]: 'Program Files'

# url路径
In [49]: p.as_uri()
Out[49]: 'file:///c:/Program%20Files'

11.1.3. Concrete路径

在原有PurePath的基础上又提供了对路径对象执行系统调用的方法。

# 当前目录,current workspace directory
In [51]: Path.cwd()
Out[51]: WindowsPath('E:/ZhaojiediProject/github/My_Aliyun_Hexo_Blog/hexo')

# 当前用户的家目录
In [52]: Path.home()
Out[52]: WindowsPath('C:/Users/Administrator')

# 目录是否存在
In [53]: Path(".").exists()
Out[53]: True

# 其他方法
In [57]: Path.
        absolute()        chmod()           expanduser()      is_absolute()     is_fifo()
        anchor            cwd()             glob()            is_block_device() is_file()
        as_posix()        drive             group()           is_char_device()  is_reserved()     >
        as_uri()          exists()          home()            is_dir()          is_socket()

11.2. os.path

这个模块算是用的比较多的,目录判断和文件相关的大部分功能都有。

os.path.abspath(path)                       绝对路径
os.path.basename(path)                      基名
os.path.commonpath(paths)                   公共路径
os.path.commonprefix(list)                  公共前缀
os.path.dirname(path)                       目录名
os.path.exists(path)                        存在判断
os.path.lexists(path)                       链接文件存在判断
os.path.expanduser(path)                    解析~这里路径
os.path.expandvars(path)                    解析变量
os.path.getatime(path)                      atime
os.path.getmtime(path)                      mtime
os.path.getctime(path)                      ctime
os.path.getsize(path)                       文件大小
os.path.isabs(path)                         判断绝对路径
os.path.isfile(path)                        判断是否是文件
os.path.isdir(path)                         判断是否是目录
os.path.islink(path)                        判断是否是链接文件
os.path.ismount(path)                       判断是否是一个挂载点
os.path.join(path, *paths)                  合并路径
os.path.normcase(path)                      忽略大小写路径
os.path.normpath(path)                      A//B, A/B/, A/./B and A/foo/../B all become A/B
os.path.realpath(path)                      相对路径
os.path.relpath(path, start=os.curdir)      相对路径
os.path.samefile(path1, path2)              相同文件
os.path.sameopenfile(fp1, fp2)              相同文件描述符
os.path.samestat(stat1, stat2)              相同stat信息
os.path.split(path)                         路径分割
os.path.splitdrive(path)                    分割驱动盘
os.path.splitext(path)                      扩展,用于提取不带扩展的文件名字

11.3. fileinput

该模块实现了一个辅助类和函数,可以在标准输入或文件列表上快速编写循环。

import fileinput
for line in fileinput.input():
    print(line)

11.4. stat

stat模块定义用于解释os.stat(),os.fstat()和os.lstat()(如果它们存在)的结果的常量和函数。

stat.S_ISDIR(mode)              是否是一个目录
stat.S_ISCHR(mode)              字符设备
stat.S_ISBLK(mode)              块设备
stat.S_ISREG(mode)              普通文件
stat.S_ISFIFO(mode)             管道文件
stat.S_ISLNK(mode)              连接文件
stat.S_ISSOCK(mode)             socket文件
stat.S_ISDOOR(mode)             不清楚这个
stat.S_ISPORT(mode)             时间端口
stat.S_ISWHT(mode)              不清楚
stat.S_IMODE(mode)              mode信息,可以后续使用so.chmod
stat.S_IFMT(mode)
stat.filemode(mode)             转化为string格式的-rwxrwxrwx
stat.ST_MODE                    inode包括mode
stat.ST_INO                     inode号码
stat.ST_DEV
stat.ST_NLINK                   inode的连接个数
stat.ST_UID                     所有者
stat.ST_GID                     所属组
stat.ST_SIZE                    大小
stat.ST_ATIME                   atime
stat.ST_MTIME                   mtime
stat.ST_CTIME                   ctime
stat.S_IFSOCK                   socket
stat.S_IFLNK                    符号连接
stat.S_IFREG                    普通文件
stat.S_IFBLK                    块设备
stat.S_IFDIR                    目录
stat.S_IFCHR                    字符
stat.S_IFIFO                    管道
stat.S_IFDOOR
stat.S_IFPORT
stat.S_IFWHT
stat.S_ISUID                    uid
stat.S_ISGID                    gid
stat.S_ISVTX
stat.S_IRWXU                    对于所有者的掩码
stat.S_IRUSR                    所有者是否有读权限
stat.S_IWUSR                    所有者是否有写权限
stat.S_IXUSR                    所有者是否有执行权限
stat.S_IRWXG                    组的掩码
stat.S_IRGRP                    组能读文件
stat.S_IWGRP                    组能写文件
stat.S_IXGRP                    组能执行文件
stat.S_IRWXO                    其他用户的掩码
stat.S_IROTH                    其他读
stat.S_IWOTH                    其他写
stat.S_IXOTH                    其他执行
stat.S_ENFMT
stat.S_IREAD
stat.S_IWRITE
stat.S_IEXEC
stat.UF_NODUMP
stat.UF_IMMUTABLE
stat.UF_APPEND
stat.UF_OPAQUE
stat.UF_NOUNLINK
stat.UF_COMPRESSED
stat.UF_HIDDEN
stat.SF_ARCHIVED
stat.SF_IMMUTABLE
stat.SF_APPEND
stat.SF_NOUNLINK
stat.SF_SNAPSHOT
In [76]: mode =os.stat(".").st_mode

In [77]: stat.S_ISDIR(mode)
Out[77]: True

11.5. filecmp

这个目录定义了一些文件和目录比较的功能。

report()                    报告比较信息
report_partial_closure()    报告包括自路径
report_full_closure()       公共子目录的比较
left                        第一个比较的目录a
right                       第二个比较的目录b
left_list                   目录a,隐藏文件被忽略
right_list                  右侧b,
common                      公共的文件和目录
left_only                   只在a目录里面存在的文件和目录
right_only                  只在b目录里面存在的文件和目录
common_dirs                 目录a和目录b公共的目录
common_files                目录a和目录b公共的文件
common_funny
same_files                  相同的文件
diff_files                  不同的文件
funny_files
subdirs
# 文件比较的
In [1]: import filecmp

In [2]: filecmp.cmp("a.txt","b.txt")
Out[2]: False

下面的代码在linux测试的。

root@centos-7 tmp]# tree
.
├── dir1
│   ├── sub1
│   │   └── a.txt
│   ├── sub2
│   └── sub3
└── dir2
    ├── sub1
    │   └── aa.txt
    ├── sub2
    └── sub4
[root@centos-7 tmp]# bpython
bpython version 0.16 on top of Python 2.7.5 /usr/bin/python
>>> import filecmp
>>> filecmp.dircmp("dir1","dir2")
<filecmp.dircmp instance at 0x1799a28>
>>> info = filecmp.dircmp("dir1","dir2")
>>> info.left
'dir1'
>>> info.right
'dir2'
>>> info.report
<bound method dircmp.report of <filecmp.dircmp instance at 0x1799a70>>
>>> info.report()
diff dir1 dir2
Only in dir1 : ['sub3']
Only in dir2 : ['sub4']
Common subdirectories : ['sub1', 'sub2']

11.6. tempfile

从名字上就知道这个是临时文件相关的。

比较简单,直接上个例子吧。

# 使用临时文件
In [1]: import tempfile

In [2]: fp =tempfile.TemporaryFile()

In [3]: fp.write(b'my name is zhaojiedi')
Out[3]: 20

In [4]: fp.seek(0)
Out[4]: 0

In [5]: fp.read()
Out[5]: b'my name is zhaojiedi'

In [6]: fp.close()

# 直接创建一个临时文件,可以后续使用open打开,在删除这个文件
In [8]: b=tempfile.mktemp("a.txt")

In [10]: b
Out[10]: 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\tmpsf5u5xiua.txt'

# 创建有名字的临时文件
In [11]: f = tempfile.NamedTemporaryFile(delete=False)

In [12]: f.name
Out[12]: 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\tmp8gj9s2o_'

In [13]: f.write(b'test')
Out[13]: 4

In [15]: import os

In [16]: os.path.exists(f.name)
Out[16]: True

In [17]: f.close()

In [18]: os.path.exists(f.name)
Out[18]: True

# 这个地方unlink下,他就被删除了
In [19]: os.unlink(f.name)

In [20]: os.path.exists(f.name)
Out[20]: False

11.7. glob

提供通配功能去查找文件的。

In [38]: glob.glob('*.zip')
Out[38]: ['backup.zip']
In [39]: glob.glob("**/*.txt",recursive=True)
Out[39]: ['2.txt', 'sub/3.txt']

11.8. fnmatch

此模块提供对Unix shell风格通配符的支持,这与正则表达式(在re模块中记录)不同。

模式

描述

*

任何的

?

单个字符

[seq]

集合里面的任何一个

[^seq]

除了集合的任何一个

# 找到当前目录下的所有txt文件
import fnmatch
import os

for file in os.listdir('.'):
    if fnmatch.fnmatch(file, '*.txt'):
        print(file)

11.9. linecache

linecache模块允许从Python源文件中获取任何行,同时尝试使用缓存进行内部优化,这是 一种从单个文件中读取多行的常见情况。

In [40]: import linecache

In [41]: linecache.getline(linecache.__file__,8)
Out[41]: 'import functools\n'

11.10. shutil

这个模块提供高级别的文件操作,比较递归copy文件等。

shutil.copyfile(src, dst, *, follow_symlinks=True)                          复制文件
shutil.copymode(src, dst, *, follow_symlinks=True)                          复制mode
shutil.copystat(src, dst, *, follow_symlinks=True)                          复制stat的atime,ctime,mtime信息
shutil.copy(src, dst, *, follow_symlinks=True)                              复制文件,支持目录的
shutil.copy2(src, dst, *, follow_symlinks=True)                             相比copy保留文件元数据信息
shutil.ignore_patterns(*patterns)
shutil.rmtree(path, ignore_errors=False, onerror=None)                      删除目录
shutil.move(src, dst, copy_function=copy2)                                  移动文件或者目录
shutil.disk_usage(path)                                                     磁盘使用情况
shutil.chown(path, user=None, group=None)                                   改变所有者,可以改组
shutil.which(cmd, mode=os.F_OK | os.X_OK, path=None)                        命令的路径
shutil.get_archive_formats()                                                获取归档格式
shutil.register_archive_format(name, function[, extra_args[, description]]) 注册归档格式
shutil.unregister_archive_format(name)                                      取消归档格式
shutil.unpack_archive(filename[, extract_dir[, format]])                    解压归档
shutil.unregister_unpack_format(name)                                       取消加压格式
shutil.get_terminal_size(fallback=(columns, lines))                         获取终端大小

使用样例:

# 复制src到dst目录,处理*.pyc和tmp*文件
from shutil import copytree, ignore_patterns
copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))

# 压缩文件
In [6]: make_archive("帮助文档","gztar","E:\\帮助文档")
Out[6]: 'C:\\Users\\Administrator\\帮助文档.tar.gz'
# 解压文件,可以不用指定格式,它内部自动根据扩展名字识别的
In [7]: from shutil import unpack_archive

In [8]: unpack_archive( 'C:\\Users\\Administrator\\帮助文档.tar.gz',"d:\\test")

11.11. macpath