使用檔案系統(filesystem):例如用來指定檔案的路徑、檔案與目錄重新命名、建立或移動檔案等。
而不同作業系統有不同的檔案系統,所以需要一些使用技巧。
作法:
使用os與os.path模組
Python 3.5
之後,增加新的pathlib模組,其提供更加物件導向、更一致的做法來完成與os與os.path相同的操作
所有作業系統皆使用字串來指定檔案與目錄。
幾乎所有作業系統都是樹狀結構來建立路徑。
磁碟機可視為樹狀結構的根。
資料夾、子資料夾則是樹狀結構的分支。
路徑名稱的開頭為「根目錄」,中間由一系列的資料夾所組成。
路徑名稱的最底層則為所需要的檔案
Linux/UNIX與Mac OS中用於分隔目錄的符號為/
Windiows中的分隔符號為\
Linux/UNIX檔案系統只有單一的根目錄
在Windows檔案系統,每個磁碟機都有獨立的一個根目錄,標記為A:\、B:\、C:\等
為了解決不同作業系統的差異,Python提供相關函數以方便程式指定檔案的路徑,以確保程式在任何檔案系統下正常執行。
絕對(absolute)路徑:
絕對路徑從檔案系統的根目錄開始,列出該檔案的完整路徑:
Windows:
C:\Proggram Files\Doom <---從 C:\ 根目錄開始
D:\backup\data <---從 D:\ 根目錄開始
Linux:
/bin/Doom <---從 / 根目錄開始Mac:
/Applications/Utilities <---從 / 根目錄開始相對(relative)路徑:
為檔案相對於檔案系統某一參考點的位置,故同樣的一個相對路徑,會因參考點的不同,最後指到的位置會不同。
Windows:
mydata\project1\main.py
games\data
Linux/Mac:
mydata/project1/main.py
games/test
Utilities/Java
相對路徑最終結果取決於參考點,常見有兩種方式:
相對路徑附加在已有的絕對路徑後面,從而產生新的絕對路徑。
相對路徑:Start Menu\Programs\Startup
絕對路徑:C:\Users\Administrator
新的絕對路徑:C:\Users\Administrator\Start Menu\Programs\Startup
將目前工作路徑(current working directory)做為參考點。
os.getcwd()進行查詢import os
os.getcwd()
## 'C:\\Users\\zheng\\Documents'
\\
來表示路徑的分隔符號。os.listdir(os.curdir)
## ['.Rhistory', '.tmp.driveupload', 'boost_1_82_0', 'C++在財務工程.docx', 'desktop.ini', 'E-book', 'HP Victus使用手冊.pdf', 'HP使用指南.pdf', 'mathproj', 'My Music', 'My Pictures', 'My Videos', 'NCCU111_2', 'OneNote Notebooks', 'Python Scripts', 'QuantLib-1.30', 'R 資料科學與統計(一).pptx', 'R 資料科學與統計(三).pptx', 'R 資料科學與統計(二).pptx', 'R 資料科學與統計(四).pptx', 'rsconnect', 'SI_Test', 'temp', 'using_filesystem.html', 'using_filesystem.Rmd', 'Visual Studio 2022', 'WindowsPowerShell', '~$+在財務工程.docx', '自訂 Office 範本']
os.listdir('.') # '.' 代表目前工作目錄
## ['.Rhistory', '.tmp.driveupload', 'boost_1_82_0', 'C++在財務工程.docx', 'desktop.ini', 'E-book', 'HP Victus使用手冊.pdf', 'HP使用指南.pdf', 'mathproj', 'My Music', 'My Pictures', 'My Videos', 'NCCU111_2', 'OneNote Notebooks', 'Python Scripts', 'QuantLib-1.30', 'R 資料科學與統計(一).pptx', 'R 資料科學與統計(三).pptx', 'R 資料科學與統計(二).pptx', 'R 資料科學與統計(四).pptx', 'rsconnect', 'SI_Test', 'temp', 'using_filesystem.html', 'using_filesystem.Rmd', 'Visual Studio 2022', 'WindowsPowerShell', '~$+在財務工程.docx', '自訂 Office 範本']
os.listdir(os.curdir)與os.listdir('.')都會回傳目前工作目錄下的所有子目錄與檔案清單,但有可能其他作業系統不會使用
'.'來代表目前目錄,為保持程式的可攜性,建議使用os.curdir來表示「目前目錄」。
使用os.chdir()函數來改變目前的工作目錄
os.chdir("C:\\")
os.getcwd()
## 'C:\\'
os.listdir(os.curdir)
## ['$Recycle.Bin', '$WinREAgent', 'AVScanner.ini', 'Config.Msi', 'dism.log', 'Documents and Settings', 'DumpStack.log', 'DumpStack.log.tmp', 'hiberfil.sys', 'hp', 'hpswsetup', 'Intel', 'Microsoft', 'office19rpt.pdf', 'OneDriveTemp', 'pagefile.sys', 'PerfLogs', 'Program Files', 'Program Files (x86)', 'ProgramData', 'Recovery', 'rtools43', 'swapfile.sys', 'swsetup', 'System Volume Information', 'System.sav', 'Users', 'Windows']
注意,在Windows系統中,雖然分隔符號為 \
,但也可以使用 /
來輸入路徑名稱。因為Python在存取Windows作業系統之前會將其進行轉換。
os.chdir('G:\\其他電腦\MacBook Pro 14\\Documents\\R386')
os.chdir('G:/其他電腦/MacBook Pro 14/Documents/R386')
os.getcwd()
## 'G:\\其他電腦\\MacBook Pro 14\\Documents\\R386'pathlib存取目錄import pathlib
cur_path = pathlib.Path() # 建立Path路徑物件
cur_path.cwd() # 取得目前工作目錄
## WindowsPath('C:/Users/zheng/Documents')
os.path提供有用的路徑處裡函數。
os.path.join()函數會將其參數字串連結起來,形成一個表示相對路徑的字串(依作業系統)。
import os
os.path.join('bin', 'utils', 'disktools') # Windows OS
## 'bin\\utils\\disktools'
# 不好的做法
os.path.join('mydir\\bin', 'utils\\disktools\\chkdisk')
## 'mydir\\bin\\utils\\disktools\\chkdisk'
# 建議做法
path1 = os.path.join('mydir', 'bin')
path2 = os.path.join('utils','disktools','chkdisk')
os.path.join(path1, path2)
## 'mydir\\bin\\utils\\disktools\\chkdisk'
import os
os.path.split(os.path.join('some', 'directory', 'path.jpg'))
## ('some\\directory', 'path.jpg')
os.path.basename(os.path.join('some', 'directory', 'path.jpg')) # 只回傳basename
## 'path.jpg'
os.path.dirname(os.path.join('some', 'directory', 'path.jpg')) # 只回傳路徑中不包含basename的部分
## 'some\\directory'
os.path.splitext(os.path.join('some', 'directory', 'path.jpg'))
## ('some\\directory\\path', '.jpg')
os.path.abspath()取得絕對路徑。import os
os.path.abspath("using_filesystem.html")
## 'C:\\Users\\zheng\\Documents\\using_filesystem.html'
pathlibfrom pathlib import Path
cur_path = Path()
cur_path
## WindowsPath('.')
print(cur_path.joinpath('bin', 'utils', 'disktools'))
## bin\utils\disktools
cur_path / 'bin' / 'utils' / 'disktools'
## WindowsPath('bin/utils/disktools')
a_path = Path('bin/utils/disktools')
a_path.parts
## ('bin', 'utils', 'disktools')
a_path = Path('.') # 目前工作路徑
a_path.resolve() # 取得絕對路徑
## WindowsPath('C:/Users/zheng/Documents')
a_path = Path('some', 'directory', 'path.jpg')
a_path.name
## 'path.jpg'
a_path.parent
## WindowsPath('some/directory')
a_path.suffix
## '.jpg'
os.curdir():目前目錄
os.pardir():上層目錄
.:代表目前目錄
..:代表上層目錄
os.curdir
## '.'
os.pardir
## '..'
import os
path = os.path.join("C:\\Windows\\temp", os.pardir, os.curdir)
path # 指向的目錄是:C:\Windows\
## 'C:\\Windows\\temp\\..\\.'
os.path.isdir(os.path.join("C:\\Windows\\temp", os.pardir, os.curdir))
## True
import os
# 檢查目錄存在與否
# path = '/path/to/directory'
if os.path.isdir(path):
print(f"{path} 是一個目錄")
else:
print(f"{path} 不是一個目錄")
## C:\Windows\temp\..\. 是一個目錄
import os
os.name
## 'nt'
import sys
sys.platform # 即使是64位元版本的Windowns
## 'win32'
os.path.exits(路徑):檢查路徑是否在檔案系統中,若存在則回傳True,否則回傳False。
os.path.isfile(路徑):檢查路徑是否指向檔案,若是則回傳True,否則回傳False。
os.path.isdir(路徑):檢查路徑是否指向目錄,若是則回傳True,否則回傳False。
import os
os.path.exists('C:\\Users\\myuser\\My Documents')
## False
os.path.exists('C:\\Users\\myuser\\My Documents\\Letter.doc')
## False
os.path.exists('C:\\Users\\myuser\\\My Documents\\ljsljkflkjs')
## False
os.path.isdir('C:\\Users\\myuser\\My Documents')
## False
os.path.isfile('C:\\Users\\ myuser\\My Documents')
## False
os.path.isdir('C:\\Users\\ myuser\\My Documents\\Letter.doc')
## False
os.path.isfile('C:\\Users\\ myuser\\My Documents\\Letter.doc')
## False
os.walk()處裡所有子目錄的所有檔案os.walk()
可遞迴地查詢目錄下所有子目錄,接著傳回該目錄與其下每個子目錄的三個資訊:
目錄路徑
子目錄清單
檔案清單
ex:資料夾階層
| temp | dir1 | file3.txt | |
| file4.txt | |||
| dir2 | dir3 | file6.txt | |
| file7.txt | |||
| file5.txt | |||
| file1.txt | |||
| file2.txt |
import os
os.getcwd()
## 'C:\\Users\\zheng\\Documents'
for entry in os.walk("temp"):
print(entry)
## ('temp', ['dir1', 'dir2'], ['file1.txt', 'file2.txt'])
## ('temp\\dir1', [], ['file3.txt', 'file4.txt'])
## ('temp\\dir2', ['dir3'], ['file5.txt'])
## ('temp\\dir2\\dir3', [], ['file6.txt', 'file7.txt'])
ls = os.walk("temp")
next(ls)
## ('temp', ['dir1', 'dir2'], ['file1.txt', 'file2.txt'])
next(ls)
## ('temp\\dir1', [], ['file3.txt', 'file4.txt'])
若參數
topdown設定為True,則在每個目錄會先處裡檔案,然後才是子目錄
若參數
topdown設定為False,則優先處裡每個資料夾的子目錄,產生由下層子目錄開始到最上層目錄的清單。
for entry in os.walk("temp", topdown = False):
print(entry)
## ('temp\\dir1', [], ['file3.txt', 'file4.txt'])
## ('temp\\dir2\\dir3', [], ['file6.txt', 'file7.txt'])
## ('temp\\dir2', ['dir3'], ['file5.txt'])
## ('temp', ['dir1', 'dir2'], ['file1.txt', 'file2.txt'])
## Example:
# import os
# for root, dir, files in os.walk(os.curdir):
# print("{0} has {1} files".format(root, len(files)))
# if ".git" in dirs: # 檢查子目錄list是否包含.git的名稱
# dir.remove(".git") # 從子目錄list中移除名為.git的目錄