Python 目录操作
[摘要] 主要内容:windows/linux下路径操作,介绍os.path和pathlib.Path两个模块,路径拼接和拆解(操作符,分解),joinpath,获取路径,父目录,其它目录操作方法,通配符,匹配。
os.path 路径操作 (3.4之前)
pathlib.Path (3.4之后推荐使用的模块)
3.4 版本之前
使用标准库os.path 模块
#linux下与windows下的默认路径分隔符不同
#linux下 In [1]: from os import path In [2]: p = path.join('/etc','sysconfig','network') In [3]: p Out[3]: '/etc/sysconfig/network' #linux默认是'/'为路径分隔符 In [7]: os.name Out[7]: 'posix' #windows下 In [1]: from os import path In [2]: p = path.join('/etc','sysconfig','network') In [3]: p Out[3]: '/etc\\sysconfig\\network' #windows是'\'反斜杠,'\\’是对'\'转义 In [15]: os.name Out[15]: 'nt'
以下内容将全部以windows下为主,与linux大同小异,只需要注意路径的写法,nt表示windows,posix表示linux即可,windows是以驱动器为起始路径,linux是以'/'为起始路径。
os.path模块常用方法:
In [34]: from os import path #导入path模块 In [35]: p = path.join('/etc','sysconfig','network') #拼接一个path In [36]: p Out[36]: '/etc\\sysconfig\\network' In [37]: type(p) Out[37]: str In [38]: path.exists(p) #判断'p'这个path路径在当前系统下是否存在 Out[38]: False In [39]: path.split(p) #将path分割为两部分(head,tail),tail为最后一个路径 Out[39]: ('/etc\\sysconfig', 'network') In [40]: p1 = '.' #'.'表示当前目录 In [41]: path.abspath(p1) #返回指定path的绝对路径 Out[41]: 'C:\\Users\\admin\\Desktop\\fileDir' In [43]: p2 = 'abc' In [44]: path.abspath(p2) Out[44]: 'C:\\Users\\admin\\Desktop\\fileDir\\abc' In [45]: p3 = path.abspath(p2) In [46]: path.dirname(p3) #目录路径 Out[46]: 'C:\\Users\\admin\\Desktop\\fileDir' In [47]: path.basename(p3) #文件基名 Out[47]: 'abc' In [48]: p3 Out[48]: 'C:\\Users\\admin\\Desktop\\fileDir\\abc' In [49]: path.splitdrive(p3) #windows下返回 drive/UNC 路径 Out[49]: ('C:', '\\Users\\admin\\Desktop\\fileDir\\abc')
其它一些方法:
os.path.isabs(path) #是否是绝对路径,返回True或False
os.path.isfile(path) #是否是文件
os.path.isdir(path) #是否是目录
os.path.islink(path) #是否是链接文件,linux下的软连接和硬链接
os.path.ismount(path) #是否是挂载文件
3.4 版本之后
3.4 版本之后则建议使用pathlib 模块,提供Path 对象来操作。包括目录和文件。
from pathlib import Path 导入
#windows下: In [50]: from pathlib import Path #Path的'p'注意大写 In [51]: p = Path() #路径初始化 In [52]: p Out[52]: WindowsPath('.') In [53]: print(type(p)) <class 'pathlib.WindowsPath'> #与linux不同 In [54]: p.absolute() Out[54]: WindowsPath('C:/Users/admin/Desktop/fileDir') #linux下: In [1]: from pathlib import Path #Path的'p'注意大写 In [2]: p = Path() In [3]: p Out[3]: PosixPath('.') In [4]: type(p) Out[4]: pathlib.PosixPath #对比与winodws的不同 In [5]: p.absolute() Out[5]: PosixPath('/home/python/magedu/project/cmdb') In [7]: p.joinpath('a','b') Out[7]: PosixPath('a/b') In [8]: p.absolute() Out[8]: PosixPath('/home/python/magedu/project/cmdb') In [9]: p = p.joinpath('a','b') #等同于os.path.join()方法,连接路径 In [10]: p.absolute() #linux默认以'/'默认路径分隔符 Out[10]: PosixPath('/home/python/magedu/project/cmdb/a/b') In [11]: p = p / 'c' / 'd' #路径拼接方法 In [12]: p Out[12]: PosixPath('a/b/c/d') In [13]: p /= 'e' #第二种路径拼接,简写成'/=' In [14]: p Out[14]: PosixPath('a/b/c/d/e') In [17]: p2 = '/etc' / 'sysconfig' #'str'和'str'不能用'/'连接 --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-17-cf6a25c9c496> in <module>() ----> 1 p2 = '/etc' / 'sysconfig' TypeError: unsupported operand type(s) for /: 'str' and 'str' In [18]: p2 = '/etc' + 'sysconfig' #符号 ’+’ 可以连接,但就不是path路径了,而是字符串 In [19]: p2 Out[19]: '/etcsysconfig' In [20]: p2 = Path('') #路径可以为空,表示当前路径 In [21]: p2 Out[21]: PosixPath('.') In [23]: p2 = p2 / '/etc/' / 'sysconfig' In [24]: p2 Out[24]: PosixPath('/etc/sysconfig') In [26]: p2 /= '.' In [27]: p2 Out[27]: PosixPath('/etc/sysconfig') In [28]: p3 = Path('a','b','c') In [29]: p3 Out[29]: PosixPath('a/b/c') In [30]: p3 = Path('/a','/b','/c') #注意连接路径时linux下不要加'/'符号,否则就表示根目录下的'/a'目录了 In [31]: p3 Out[31]: PosixPath('/c') #否则只会保存最后一个以'/'开头的path In [32]: p3 = Path('/a','/b','c') #同样 In [33]: p3 Out[33]: PosixPath('/b/c')
路径初始化:
In [32]: p = Path() #当前目录 In [33]: p Out[33]: PosixPath('.') In [34]: p = Path('a','b','c/d') #当前目录下的a/b/c/d In [35]: p Out[35]: PosixPath('a/b/c/d') In [36]: p = Path('/etc') #根目录下的etc目录 In [37]: p Out[37]: PosixPath('/etc') In [38]: p = Path('/a','b','c/d') #根目录下的/a/b/c/d目录 In [39]: p Out[39]: PosixPath('/a/b/c/d')
路径拼接和拆解
操作符 /
Path对象 / Path对象
Path对象 / 字符串 或者 字符串 / Path对象
In [41]: p Out[41]: PosixPath('.') In [42]: p.absolute() Out[42]: PosixPath('/home/python/magedu/project/cmdb') In [43]: p = p / 'a' In [44]: p Out[44]: PosixPath('a') In [45]: p.absolute() Out[45]: PosixPath('/home/python/magedu/project/cmdb/a')
分解
parts属性,可以返回路径中的每一个部分
In [47]: p2 = Path('/etc','sysconfig') In [48]: p2 Out[48]: PosixPath('/etc/sysconfig') In [50]: p2.parts Out[50]: ('/', 'etc', 'sysconfig') In [51]: str(p2.parts) Out[51]: "('/', 'etc', 'sysconfig')" In [52]: str(p2.parts) + '/abc/d' Out[52]: "('/', 'etc', 'sysconfig')/abc/d" In [53]: str(p2) + '/abc/d' Out[53]: '/etc/sysconfig/abc/d' In [54]: p2 + 'a' --------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-54-43da11262e30> in <module>() ----> 1 p2 + 'a' TypeError: unsupported operand type(s) for +: 'PosixPath' and 'str'
joinpath
joinpath(*other) 连接多个字符串到Path对象中
In [59]: p = Path() In [60]: p Out[60]: PosixPath('.') In [61]: p = p / 'a' In [62]: p1 = 'b' / p In [63]: p2 = Path('c') In [64]: p3 = p2 / p1 In [65]: print(p3.parts) ('c', 'b', 'a') In [66]: p3.joinpath('/etc','init.d',Path('nginx')) Out[66]: PosixPath('/etc/init.d/nginx') In [67]: p Out[67]: PosixPath('a') In [68]: p1 Out[68]: PosixPath('b/a') In [69]: p2 Out[69]: PosixPath('c') In [70]: p3 Out[70]: PosixPath('c/b/a')
获取路径
str 获取路径字符串
bytes 获取路径字符串的bytes
In [71]: p = Path('/etc') In [72]: print(str(p),bytes(p)) /etc b'/etc'
父路径(父目录)
parent 目录的逻辑父目录
parents 父目录序列,索引0是直接的父
In [75]: p2 = Path('/etc','sysconfig') In [76]: p2 Out[76]: PosixPath('/etc/sysconfig') In [77]: p2.encode() ........... AttributeError: 'PosixPath' object has no attribute 'encode' In [79]: str(p2).encode() #转为str再转bytes Out[79]: b'/etc/sysconfig' In [80]: bytes(p2) Out[80]: b'/etc/sysconfig' In [81]: p2.parts Out[81]: ('/', 'etc', 'sysconfig') In [85]: p2.parents Out[85]: <PosixPath.parents> In [86]: p2.parent #返回每一级的父目录 Out[86]: PosixPath('/etc') In [87]: p2.parent.parent Out[87]: PosixPath('/') In [88]: p2.parent.parent.parent Out[88]: PosixPath('/') In [89]: p2.parent.parent.parent.parent #linux最高父目录只能是'/'根, Out[89]: PosixPath('/') In [92]: p3 /= 'a/b/c/d' In [93]: list(p3.parents) Out[93]: [PosixPath('c/b/a/a/b/c'), PosixPath('c/b/a/a/b'), PosixPath('c/b/a/a'), PosixPath('c/b/a'), PosixPath('c/b'), PosixPath('c'), PosixPath('.')] In [94]: p3 Out[94]: PosixPath('c/b/a/a/b/c/d') In [95]: del p3 In [96]: p Out[96]: PosixPath('/etc') In [106]: p3 = Path('/etc') / 'sysconfig' / 'a/b/c/d' In [107]: p3 Out[107]: PosixPath('/etc/sysconfig/a/b/c/d') In [108]: list(p3.parents) #列表格式返回所有每一级父路径 Out[108]: [PosixPath('/etc/sysconfig/a/b/c'), PosixPath('/etc/sysconfig/a/b'), PosixPath('/etc/sysconfig/a'), PosixPath('/etc/sysconfig'), PosixPath('/etc'), PosixPath('/')] In [109]: list(p3.parents)[2] #既然是列表就可以用索引 Out[109]: PosixPath('/etc/sysconfig/a') In [110]: list(p3.parents)[-1] Out[110]: PosixPath('/') In [129]: p4 = Path() In [130]: p4.absolute() Out[130]: PosixPath('/home/python/magedu/project/cmdb') In [131]: p4.absolute().parents Out[131]: <PosixPath.parents> In [132]: list(p4.absolute().parents) #绝对路径的每一级父路径 Out[132]: [PosixPath('/home/python/magedu/project'), PosixPath('/home/python/magedu'), PosixPath('/home/python'), PosixPath('/home'), PosixPath('/')]
其它方法:
name、stem、suffix、suffixes、whth_suffix(suffix)、with_name(name)
name 目录的最后一个部分
suffix 目录中最后一个部分的扩展名
stem 目录最后一个部分,没有后缀
suffixes 返回多个扩展名列表
with_suffix(suffix) 补充扩展名到路径尾部,返回新的路径,扩展名存在则无效
with_name(name) 替换目录最后一个部分并返回一个新的路径
In [135]: p5 = Path('/etc/sysconfig/network/xxx.tar.gz') In [136]: p5.stem Out[136]: 'xxx.tar' In [137]: p5.name Out[137]: 'xxx.tar.gz' In [138]: p5.suffix Out[138]: '.gz' In [139]: p5.suffixes Out[139]: ['.tar', '.gz'] In [140]: p5.with_suffix('gz') ........略 ValueError: Invalid suffix 'gz' In [141]: p5.with_suffix('.gz') #当前就是'.gz'后缀,看不到效果 Out[141]: PosixPath('/etc/sysconfig/network/xxx.tar.gz') In [142]: p5.with_suffix('.jz') #替换为'.jz' Out[142]: PosixPath('/etc/sysconfig/network/xxx.tar.jz') In [144]: p5.with_suffix('.zip') #替换为'.zip' Out[144]: PosixPath('/etc/sysconfig/network/xxx.tar.zip') In [145]: p5 Out[145]: PosixPath('/etc/sysconfig/network/xxx.tar.gz') In [146]: p5.with_name('yyy.txt') #替换文件名'yyy.txt' Out[146]: PosixPath('/etc/sysconfig/network/yyy.txt') In [147]: p5.with_name('zzz.txt') Out[147]: PosixPath('/etc/sysconfig/network/zzz.txt') In [155]: p3 = Path('/etc/sysconfig/network/back.tar.gz') In [164]: p5.with_name(p3.name) Out[164]: PosixPath('/etc/sysconfig/network/back.tar.gz')
cwd() 返回当前工作目录
home() 返回当前家目录
is_dir() 是否是目录
is_file() 是否是普通文件
is_symlink() 是否是软链接
is_socket() 是否是socket文件
is_block_device() 是否是块设备
is_char_device() 是否是字符设备
is_absolute() 是否是绝对路径
resolve() 返回一个新的路径,这个路径就是当前Path对象的绝对路径,如果是软链接则直接被解析
absolute() 也可以获取绝对路径,但是推荐使用resolve()
exists() 目录或文件是否存在
move() 移动目录或文件
rmdir() 删除空目录。没有提供判断目录为空的方法
touch(mode=0o666,exist_ok=True) 创建一个文件
as_uri() 将路径返回URI,例如'file:///etc/password'
mkdir(mode=0o755,parents=False,esist_ok=False)
parents,是否创建父目录,True等同于mkdir -p;Flase时,父目录不存在,抛出异常 FileNotFoundError
exist_ok 参数,在3.5版本加入。False时,路径存在,抛出FileExistsError;True时,FileExistsError被忽略
iterdir()
迭代当前目录
以上各种方法举例:
In [172]: p6 = Path() In [173]: p6 Out[173]: PosixPath('.') In [175]: p6.cwd() Out[175]: PosixPath('/home/python/magedu/project/cmdb') In [176]: p6.home() Out[176]: PosixPath('/home/python') In [183]: p6 = Path('log') In [184]: p6 Out[184]: PosixPath('log') In [185]: p6.exists() Out[185]: False In [187]: p6.mkdir(mode=0o777,parents=False,exist_ok=False) #创建这个log目录,0o表示8进制(0x,16进制,0b,2进制),777表示权限(rwx) In [188]: ls log/ In [195]: p7 = Path('1.txt') In [196]: p7.touch(mode=0o666,exist_ok=True) #创建这个文件,如果文件已存在,会将修改时间更新为当前时间 In [197]: ls 1.txt log/ In [198]: p7.touch(mode=0o666,exist_ok=False) #如果文件已存在,返回异常 FileExistsError .......略 FileExistsError: [Errno 17] File exists: '1.txt' In [27]: shutil.move('/home/python/copyfile.txt','/home/python/magedu/project/cmdb/copyfile.txt') Out[27]: '/home/python/magedu/project/cmdb/copyfile.txt' In [28]: ls copyfile.txt
通配符
glob(pattern) 通配给定的模式
rglob(pattern) 通配给定的模式,递归目录
举例:
list(p6.glob('*.conf')) #仅查找当前目录下'.conf'结尾的配置文件
list(p6.glob('**/*.conf')) #递归'/etc'下所有目录查找'.conf'结尾的配置文件
list(p6.rglob('*.conf')) #也是递归查找,等同于list(p6.glob('**/*.conf'))
In [213]: list(p6.glob('*.conf')) #仅查找当前目录下'.conf'结尾的配置文件 Out[213]: [PosixPath('/etc/resolv.conf'), PosixPath('/etc/yum.conf'), PosixPath('/etc/host.conf'), ....略 PosixPath('/etc/rsyncd.conf'), PosixPath('/etc/fprintd.conf'), PosixPath('/etc/ntp.conf')] In [214]: list(p6.glob('**/*.conf')) #递归'/etc'下索引目录查找'.conf'结尾的配置文件 Out[214]: [PosixPath('/etc/resolv.conf'), PosixPath('/etc/libuser.conf'), PosixPath('/etc/yum.conf'), PosixPath('/etc/dracut.conf'), PosixPath('/etc/host.conf'), ....略 PosixPath('/etc/security/pam_env.conf'), PosixPath('/etc/security/sepermit.conf'), PosixPath('/etc/security/time.conf'), PosixPath('/etc/plymouth/plymouthd.conf'), PosixPath('/etc/tuned/tuned-main.conf')] In [215]: list(p6.rglob('*.conf')) #等同于list(p6.glob('**/*.conf')) Out[215]: [PosixPath('/etc/resolv.conf'), PosixPath('/etc/yum.conf'), PosixPath('/etc/host.conf'), PosixPath('/etc/sysctl.conf'), PosixPath('/etc/ntp.conf'), PosixPath('/etc/depmod.d/dist.conf'), ....略 PosixPath('/etc/abrt/abrt.conf'), PosixPath('/etc/security/chroot.conf'), PosixPath('/etc/security/group.conf'), PosixPath('/etc/security/limits.conf')]
匹配
match(pattern)
模式匹配,成功返回True
Path('a/b.py').match('*.py') # True Path('/a/b/c.py').match('b/*.py') # True Path('/a/b/c.py').match('a/*.py') # False Path('/a/b/c.py').match('a/**.py') # False Path('/a/b/c.py').match('a/*/*.py') #True Path('/a/b/c.py').match('a**.py') # False Path('/a/b/c.py').match('a**/*.py') # False Path('/a/b/c.py').match('a/**/*.py') # True Path('/a/b/c.py').match('**/*.py') #True
windows/linux下路径操作,介绍os.path和pathlib.Path两个模块,路径拼接和拆解(操作符,分解),joinpath,获取路径,父目录,其它目录操作方法,通配符,匹配。