若是咱們要操做文件,目錄,能夠在命令行下面輸入操做系統提供的各類命令來完成。好比ls,cp等命令node
若是要在python程序中執行這些目錄和文件的操做怎麼辦?其實操做系統提供的命令指示簡單地調用了操做系統提供的接口函數,Python內置的os模塊也能夠直接調用操做系統提供的接口函數python
打開Python交互式命令行,咱們來看看如何使用os
模塊的基本功能:nginx
>>> import os >>> os.name 'posix'
若是是posix
,說明系統是Linux
、Unix
或Mac OS X
,若是是nt
,就是Windows
系統。web
要獲取詳細的系統信息,能夠調用uname()
函數:redis
>>> 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
這個變量中,能夠直接查看:json
>>> 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')
:bash
>>> 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
模塊中,這一點要注意一下。查看、建立和刪除目錄能夠這麼調用:less
#查看當前目錄的絕對路徑 >>> 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()
返回這樣的字符串:svg
>>> os.path.join('part-1','part-2') 'part-1/part-2'
而在Windows下回返回這樣的字符串函數
part-1\part-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')