python基本操做-文件、目錄及路徑

使用python的os模塊,簡單方便完成對文件夾、文件及路徑的管理與訪問操做。html

1 前言

在最近開發中,常常須要對文件進行讀取、遍歷、修改等操做,想要快速、簡單的完成這些操做,我選擇用 python 。經過 python 的標準內置 os 模塊,只須要幾行代碼,便可完成想要的操做。通過對 os 的使用,本文把 os 模塊的經常使用的操做進行總結,主要分爲如下幾個劃分:java

  • 文件夾操做:即文件夾的建立、修改(更名/移動),查詢(查看、遍歷)、刪除等。
  • 文件操做:即文件的建立、修改、讀取、刪除等。
  • (文件夾/文件)路徑操做:即文件夾或文件的路徑操做,如絕對路徑,文件名與路徑分割,擴展名分割等

本文涉及經常使用 的 os 函數的使用展現,主要使用 python 交互模式下進行代碼說明。後續操做默認已經引入 os 模塊,以下:node

import os
複製代碼

2 文件夾操做

以本地 E://pythontest 目錄做爲演示目錄,此目錄下當前文件以下:python

test
 │ test.txt
 └─test-1
     test-1.txt
複製代碼

testtest-1 是文件夾,test.txttest-1.txt 是文件。linux

2.1 查詢操做

熟悉 linux 同窗應該對 ls / pwd / cd 等操做不陌生,對應的 python 也有對應的方法,主要包括:shell

  • listdir : 文件及目錄列表
  • getcwd :獲取當前目錄
  • chdir :更換目錄
  • stat :文件及目錄基本信息
  • walk :遞歸遍歷目錄
>>> os.chdir("E://pythontest")  # 更改目錄
>>> os.getcwd()                 # 獲取當前目錄
'E:\\pythontest'
>>> os.listdir("test")          # 文件及目錄列表,相對路徑
['test-1', 'test.txt']          
>>> os.listdir("E://pythontest/test")  # 文件及目錄列表,絕對路徑
['test-1', 'test.txt']
>>> os.stat("test")             # 獲取目錄信息
os.stat_result(st_mode=16895, st_ino=4503599627377599, st_dev=266147611, st_nlink=1, st_uid=0, st_gid=0, st_size=0, st_atime=1590833033, st_mtime=1590832647, st_ctime=1590832207)
>>> os.stat("test/test.txt")    # 獲取文件信息
os.stat_result(st_mode=33206, st_ino=2251799813692354, st_dev=266147611, st_nlink=1, st_uid=0, st_gid=0, st_size=4, st_atime=1590832653, st_mtime=1590832609, st_ctime=1590832598)
複製代碼

其中 stat 函數返回的是文件或者目錄的基本信息,具體以下:緩存

  • st_mode: inode 保護模式
  • st_ino: inode 節點號。
  • st_dev: inode 駐留的設備。
  • st_nlink: inode 的連接數。
  • st_uid: 全部者的用戶ID。
  • st_gid: 全部者的組ID。
  • st_size: 普通文件以字節爲單位的大小
  • st_atime: 上次訪問的時間。
  • st_mtime: 最後一次修改的時間。
  • st_ctime: 建立時間。

平常使用中,咱們通常使用 st_size 、st_ctime 及 st_mtime 獲取文件大小,建立時間,修改時間。另外,咱們看到輸出的時間是秒數,在這裏提一下,關於日期的轉換處理。分佈式

(1)秒數轉日期時間格式字符串函數

>>> import time                              # 引入time模塊
>>> timestruct = time.localtime(1590803070)  # 轉換爲時間結構體
>>> print(timestruct)
time.struct_time(tm_year=2020, tm_mon=5, tm_mday=30, tm_hour=9, tm_min=44, tm_sec=30, tm_wday=5, tm_yday=151, tm_isdst=0)
>>> time.strftime("%Y-%m-%d %H:%M:%S",timestruct)   # 格式化時間
'2020-05-30 09:44:30'
複製代碼

(2)格式日期時間字符串轉秒數ui

>>> import datetime               # 引入datetime模塊
>>> timeobject = datetime.datetime.strptime("2020-05-23 10:00:00","%Y-%m-%d %H:%M:%S") #解析時間字符串爲時間對象
>>> timeseconds=time.mktime(timeobject.timetuple())  # 獲取時間秒數
>>> print(int(timeseconds))       # 轉爲int顯示
1590199200
複製代碼
  • 遍歷操做

    walk 函數對目錄進行遞歸遍歷,返回 root,dirs,files,分別對應當前的遍歷的目錄,此目錄中的子目錄及文件。

>>> data = os.walk("test")               # 遍歷test目錄
>>> for root,dirs,files in data:         # 遞歸遍歷及輸出
...    print("root:%s" % root)
...    for dir in dirs:
...       print(os.path.join(root,dir))
...    for file in files:
...       print(os.path.join(root,file))
...
root:test
test\test-1
test\test-2
test\test.txt
root:test\test-1
test\test-1\test-1.txt
root:test\test-2
test\test-2\test-2.txt
複製代碼

2.2 建立操做

  • mkdir :新建單個目錄,若目錄路徑中父目錄不存在,則建立失敗

  • makedirs :新建多個目錄,若目錄路徑中父目錄不存在,則自動建立

>>> os.mkdir("test")
>>> os.mkdir("test1/test1-1")          # 父目錄不存在,報錯
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [WinError 3] 系統找不到指定的路徑。: 'test1/test1-1'
>>> os.makedirs("test1/test1-1")       # 父目錄不存在,自動建立
>>> os.listdir("test1")
['test1-1']
複製代碼

2.3 刪除操做

  • rmdir :刪除單個空目錄,目錄不爲空則報錯
  • removedirs : 按路徑刪除遞歸多級空目錄,目錄不爲空則報錯
>>> os.rmdir("test1")                         # 若目錄不爲空,報錯
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [WinError 145] 目錄不是空的。: 'test1'
>>> os.rmdir("test1/test1-1")
>>> os.removedirs("test1/test1-1")            # 刪除多級空目錄
>>> os.listdir(".")
['test']
複製代碼

因爲刪除空目錄的限制,更多的是使用 shutil 模塊中的 rmtree 函數,能夠刪除不爲空的目錄及其文件。

2.4 修改操做

  • rename :重命名目錄或文件,可修改文件或目錄的路徑(即移動操做),若目標文件目錄不存在,則報錯。
  • renames :重命名目錄或文件,若目標文件目錄不存在,則自動建立
>>> os.makedirs("test1/test1-1")
>>> os.rename("test1/test1-1","test1/test1-2")     # test1-1 修改成test1-2
>>> os.listdir("test1")
['test1-2']
>>> os.rename("test1/test1-2","test2/test2-2")     # 因爲test2目錄不存在,報錯
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [WinError 3] 系統找不到指定的路徑。: 'test1/test1-2' -> 'test2/test2-2'
>>> os.renames("test1/test1-2","test2/test2-2")    # renames可自動建立不存在的目錄
>>> os.listdir("test2")
['test2-2']
複製代碼

若是目標路徑文件已經存在,那麼os.rename()和os.renames()都會報錯:FileExistsError: [WinError 183] 當文件已存在時,沒法建立該文件。

3 文件操做

3.1 查詢操做

  • open/read/close :文件讀取
  • stat :文件信息,詳細見前面文件夾中的 stat 說明
>>> f = os.open("test/test.txt", os.O_RDWR|os.O_CREAT)  # 打開文件
>>> str_bytes = os.read(f,100)                          # 讀100字節
>>> str = bytes.decode(str_bytes)                       # 字節轉字符串
>>> print(str)
test write data
>>> os.close(f)                                         # 關閉文件
複製代碼

注意 open/read/close 須要一塊兒操做,其中 open 操做須要指定模式,上述是以讀寫模式打開文件,若文件不存在則建立文件。各模式具體以下:

flags -- 該參數能夠是如下選項,多個使用 "|" 隔開:

  • os.O_RDONLY: 以只讀的方式打開
  • os.O_WRONLY: 以只寫的方式打開
  • os.O_RDWR : 以讀寫的方式打開
  • os.O_NONBLOCK: 打開時不阻塞
  • os.O_APPEND: 以追加的方式打開
  • os.O_CREAT: 建立並打開一個新文件
  • os.O_TRUNC: 打開一個文件並截斷它的長度爲零(必須有寫權限)
  • os.O_EXCL: 若是指定的文件存在,返回錯誤
  • os.O_SHLOCK: 自動獲取共享鎖
  • os.O_EXLOCK: 自動獲取獨立鎖
  • os.O_DIRECT: 消除或減小緩存效果
  • os.O_FSYNC : 同步寫入
  • os.O_NOFOLLOW: 不追蹤軟連接

3.2 建立操做

前面已提到,使用 open ,指定模式, 若文件不存在,則建立。有點相似 linux 操做中的 touch。

>>> f = os.open("test/test.txt", os.O_RDWR|os.O_CREAT)   # 若文件不存在,則建立
>>> os.close(f)
複製代碼

3.3 修改操做

  • open/write/close :寫入文件內容
  • rename ,renames : 與前面介紹的修更名稱、移動操做一致。
>>> f = os.open("test/test.txt", os.O_RDWR|os.O_CREAT)     # 打開文件
>>> os.write(f,b"test write data")                         # 寫入內容
15
>>> os.close(f)                                   # 關閉文件
複製代碼

3.4 刪除

  • remove :刪除文件,注意不能刪除目錄(使用 rmdir/removedirs)
>>> os.remove("test/test-1")       # 刪除目錄報錯
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [WinError 2] 系統找不到指定的文件。: 'test/test1'
>>> os.remove("test/test.txt")     # 刪除文件
>>> os.listdir("test")
['test-1']
複製代碼

4 路徑操做

在使用文件或目錄過程當中,常常須要對文件及目錄路徑進行處理,所以,os 中有一個子模塊 path,專門就是處理路徑操做的。主要有如下操做:

  • abspath :返回絕對路徑
>>> os.path.abspath("test")
'E:\\pythontest\\test'
複製代碼
  • exists :判斷文件或目錄是否存在
>>> os.path.exists("test")
True
>>> os.path.exists("test/test.txt")
False
>>> os.path.exists("test/test-1/test-1.txt")
True
複製代碼
  • isfile/isdir :判斷是否爲文件/目錄
>>> os.path.isdir("test")
True
>>> os.path.isfile("test/test-1/test-1.txt")
True
複製代碼
  • basename/dirname:獲取路徑尾部和路徑頭部。其實就是以路徑中最後一個 / 爲分割符,分爲頭(head) 和尾(tail)兩部分,tail 是 basename 返回的內容,head 是 dirname 返回的內容。常常用於獲取文件名,目錄名等操做
>>> os.path.basename("test/test-1/test-1.txt")   # 文件名
'test-1.txt'
>>> os.path.basename("test/test-1/")     # 空內容
''
>>> os.path.basename("test/test-1")      # 目錄名
'test-1'
>>> os.path.dirname("test/test-1/test-1.txt")   # 文件所在目錄路徑
'test/test-1'
>>> os.path.dirname("test/test-1/")   # 目錄路徑
'test/test-1'
>>> os.path.dirname("test/test-1")   # 父目錄路徑
'test'
複製代碼
  • join :合成路徑,即把兩個參數使用系統路徑分割符進行鏈接,造成完整路徑。
>>> os.path.join("test","test-1")   # 鏈接兩個目錄
'test\\test-1'
>>> os.path.join("test\\test-1","test-1.txt")   # 鏈接目錄與文件名
'test\\test-1\\test-1.txt'
複製代碼
  • split :分割文件名和文件夾,即把 path 以最後一個斜線"/"爲分隔符,切割爲 head 和 tail ,以 (head, tail) 元組的形勢返回。
>>> os.path.split("test/test-1")     # 分割目錄
('test', 'test-1')
>>> os.path.split("test/test-1/")    # 以/結尾的目錄分割
('test/test-1', '')
>>> os.path.split("test/test-1/test-1.txt")  # 分割文件
('test/test-1', 'test-1.txt')
複製代碼
  • splitext :分割路徑名和文件擴展名,把path 以最後一個擴展名分隔符「.」分割,切割爲 head 和 tail ,以 (head, tail) 元組的形勢返回。注意與 split 的區別是分隔符的不一樣。
>>> os.path.splitext("test/test-1")  
('test/test-1', '')
>>> os.path.splitext("test/test-1/") 
('test/test-1/', '')
>>> os.path.splitext("test/test-1/test-1.txt")  # 區分文件名及擴展名
('test/test-1/test-1', '.txt')
>>> os.path.splitext("test/test-1/test-1.txt.tmp") # 以最後的"."爲分割點
('test/test-1/test-1.txt', '.tmp')
複製代碼

5 示例應用

下面以一些平時使用到的場景,對前面的操做函數進行綜合使用。

5.1 批量修改文件名

def batch_rename(dir_path):
    itemlist = os.listdir(dir_path)
    # 獲取目錄文件列表
    for item in itemlist:
        # 鏈接成完整路徑
        item_path = os.path.join(dir_path, item)
        print(item_path)
        # 修改文件名
        if os.path.isfile(item_path):
            splitext = os.path.splitext(item_path)
            os.rename(item_path, splitext[0] + "-副本" + splitext[1])
複製代碼

批量修改文件名

5.2 遍歷目錄及子目錄下全部指定擴展名的文件

def walk_ext_file(dir_path,ext):
    # 遍歷
    for root, dirs, files in os.walk(dir_path):
        # 獲取文件名稱及路徑
        for file in files:
            file_path = os.path.join(root, file)
            file_item = os.path.splitext(file_path)
            # 輸出指定擴展名的文件路徑
            if ext == file_item[1]:
                print(file_path)
複製代碼

遍歷指定擴展名文件

5.3 按修改時間排序指定目錄下的文件

def sort_file(dir_path):
    # 排序前
    itemlist = os.listdir(dir_path)
    print(itemlist)
    # 正向排序
    itemlist.sort(key=lambda filename: os.path.getmtime(os.path.join(dir_path, filename)))
    print(itemlist)
    # 反向排序
    itemlist.sort(key=lambda filename: os.path.getmtime(os.path.join(dir_path, filename)), reverse=True)
    print(itemlist)
    # 獲取最新修改的文件
    print(itemlist[0])
複製代碼

排序文件

6 總結

在須要對文件或者目錄進行操做時,python 是一個簡單快速選擇。本文經過 python 的標準內置 os 模塊及子模塊 os.path 的經常使用方法進行介紹,最後結合使用場景進行綜合使用。相信已經知足你們對文件及目錄操做的大部分需求。

參考資料

往期文章

個人公衆號(搜索Mason技術記錄),獲取更多技術記錄:

mason
相關文章
相關標籤/搜索