如果我们要操作文件,目录,可以在命令行下面输入操作系统提供的各种命令来完成。比如ls,cp等命令
如果要在python程序中执行这些目录和文件的操作怎么办?其实操作系统提供的命令指示简单地调用了操作系统提供的接口函数,Python内置的os模块也可以直接调用操作系统提供的接口函数
打开Python交互式命令行,我们来看看如何使用os
模块的基本功能:
>>> import os >>> os.name 'posix'
如果是posix
,说明系统是Linux
、Unix
或Mac OS X
,如果是nt
,就是Windows
系统。
要获取详细的系统信息,可以调用uname()
函数:
>>> os.uname() posix.uname_result(sysname='Linux', nodename='prd-zabbix', release='3.10.0-862.el7.x86_64', version='#1 SMP Fri Apr 20 16:44:24 UTC 2018', machine='x86_64')
环境变量
在操作系统中定义的环境变量,全部保存在os.environ
这个变量中,可以直接查看:
>>> os.environ environ({'XDG_SESSION_ID': '12832', 'HOSTNAME': 'prd-zabbix', 'TERM': 'xterm', 'SHELL': '/bin/bash', 'HISTSIZE': '1000', 'SSH_CLIENT': '192.168.1.149 50998 22', 'CONDA_SHLVL': '1', 'CONDA_PROMPT_MODIFIER': '(base) ', 'SSH_TTY': '/dev/pts/0', 'USER': 'root', 'LS_COLORS': 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:', 'CONDA_EXE': '/root/anaconda3/bin/conda', '_CE_CONDA': '', 'MAIL': '/var/spool/mail/root', 'PATH': '/root/anaconda3/bin:/root/anaconda3/condabin:/usr/local/redis-4.0.9/src:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/lib/rabbitmq/bin:/usr/local/jdk1.8.0_171/bin:/usr/local/nginx/sbin:/root/bin:/root/bin:/usr/local/python3/bin', 'CONDA_PREFIX': '/root/anaconda3', 'PWD': '/root', 'JAVA_HOME': '/usr/local/jdk1.8.0_171', 'LANG': 'zh_CN.UTF-8', '_CE_M': '', 'HISTCONTROL': 'ignoredups', 'SHLVL': '1', 'HOME': '/root', 'LOGNAME': 'root', 'CLASSPATH': '/usr/local/jdk1.8.0_171/lib/', 'SSH_CONNECTION': '192.168.1.149 50998 172.16.40.232 22', 'CONDA_DEFAULT_ENV': 'base', 'LESSOPEN': '||/usr/bin/lesspipe.sh %s', 'XDG_RUNTIME_DIR': '/run/user/0', '_': '/root/anaconda3/bin/python3'})
要获取某个环境变量的值,可以调用os.environ.get('key')
:
>>> os.environ.get('PATH') '/root/anaconda3/bin:/root/anaconda3/condabin:/usr/local/redis-4.0.9/src:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/lib/rabbitmq/bin:/usr/local/jdk1.8.0_171/bin:/usr/local/nginx/sbin:/root/bin:/root/bin:/usr/local/python3/bin'
操作文件和目录
操作文件和目录的函数一部分放在os
模块中,一部分放在os.path
模块中,这一点要注意一下。查看、创建和删除目录可以这么调用:
#查看当前目录的绝对路径 >>> os.path.abspath('.') '/root' #在某个目录下创建一个新目录,首先把新目录的完整路径表示出来: >>> os.path.join('/root','testdir') '/root/testdir' #创建一个目录 >>> os.mkdir('/root/testdir') #删除一个目录 >>> os.rmdir('/root/testdir')
把两个路径合成一个时,不要直接拼字符串,而要通过os.path.join()
函数,这样可以正确处理不同操作系统的路径分隔符。在Linux/Unix/Mac下,os.path.join()
返回这样的字符串:
>>> os.path.join('part-1','part-2') 'part-1/part-2'
而在Windows下回返回这样的字符串
part-1part-2
同样的道理,要拆分路径时,也不要直接去拆字符串,而要通过os.path.split()
函数,这样可以把一个路径拆分为两部分,后一部分总是最后级别的目录或文件名:
>>> os.path.split('/root/testdir') ('/root', 'testdir')
>>> os.path.split('/root/testdir/test.txt') ('/root/testdir', 'test.txt')
os.path.splitext()
可以直接让你得到文件扩展名,很多时候非常方便:
>>> os.path.splitext('/root/testdir/test.txt') ('/root/testdir/test', '.txt')
PS:这些合并、拆分路径的函数并不要求目录和文件要真实存在,它们只对字符串进行操作。
文件操作使用下面的函数。假定当前目录下有一个test.txt
文件:
#对文件重命名 >>> os.rename('test.txt','test.py') #删除文件 >>> os.remove('test.py')
但是复制文件的函数居然在os
模块中不存在!原因是复制文件并非由操作系统提供的系统调用。理论上讲,我们通过上一节的读写文件可以完成文件复制,只不过要多写很多代码。
幸运的是shutil
模块提供了copyfile()
的函数,你还可以在shutil
模块中找到很多实用函数,它们可以看做是os
模块的补充。
最后看看如何利用Python的特性来过滤文件。比如我们要列出当前目录下的所有目录,只需要一行代码:
[x for x in os.listdir('.') if os.path.isdir(x)]
os.path.isdir(x)判断是否为目录,返回True或者False
要列出所有的.py文件,也只需一行代码
[x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']
os.path.isfile(x)判断是否文件 os.path.splitext(x)[1]=='.py'判断后缀为py
练习
1.利用os模块编写一个能实现dir -l输出的程序
2.编写一个程序,能在当前目录以及当前目录所有子目录下查找包含特定字符串的文件,并打印出相对路径
练习1 do_dir.py
#!/usr/bin/env python3 # -*- coding: utf-8 -*- from datetime import datetime import os #获取当前绝对路径,返回为字符串str pwd = os.path.abspath('.') print(' Size Last Modified Name') print('------------------------------------------------------------') #os.listdir(pwd)列出当前路径下所有文件和文件夹,结果为列表 for f in os.listdir(pwd): #获取文件夹或者文件大小 fsize = os.path.getsize(f) #格式化日期时间信息 mtime = datetime.fromtimestamp(os.path.getmtime(f)).strftime('%Y-%m-%d %H:%M') #设置尾部flag如果是文件夹则加/显示,否则是文件则flag为空 flag = '/' if os.path.isdir(f) else '' #格式化输出%10d代表输出10位,右对齐不足10位的左边加空格补齐 print('%10d %s %s%s' % (fsize, mtime, f, flag))
运行结果如下
(base) [root@prd-zabbix io]# python3 do_dir.py Size Last Modified Name ------------------------------------------------------------ 331 2019-07-08 09:32 do_bytesio.py 379 2019-07-08 09:32 do_stringio.py 673 2019-07-08 09:32 use_json.py 180 2019-07-08 09:32 use_pickle.py 386 2019-07-08 09:32 with_file.py 20 2019-07-13 10:20 test.txt 91402 2019-07-10 15:20 test.jpg 13 2019-07-10 15:43 gbk.txt 1917 2019-07-10 17:36 StringIO_BytesIO.py 22 2019-07-13 13:45 test/ 1455 2019-07-13 11:11 search_file.py 248 2019-07-13 13:53 findstr.py 464 2019-07-13 15:14 do_dir2.py 12288 2019-07-13 16:14 .do_dir.py.swp 840 2019-07-13 16:13 do_dir.py
查找目录下包含指定字符串的文件夹及文件并打印出来
findstr.py
import os #定义函数包含两个参数p为查找路径,str为需要查找包含的字符 def findstr(p,str): #遍历路径下文件夹和文件 for x in os.listdir(p): #拼接成完整路径+文件名 path=os.path.join(p,x) #如果是文件并且查找的字符串包含在文件里则打印 if os.path.isfile(path) and str in x: print(path) #如果是文件夹则递归再次调用函数 if os.path.isdir(path): findstr(path,str) findstr('test','test')