# 6.5.?與目錄共事
`os.path` 模塊有幾個操作文件和目錄的函數。這里,我們看看如何操作路徑名和列出一個目錄的內容。
## 例?6.16.?構造路徑名
```
>>> import os
>>> os.path.join("c:\\music\\ap\\", "mahadeva.mp3")
'c:\\music\\ap\\mahadeva.mp3'
>>> os.path.join("c:\\music\\ap", "mahadeva.mp3")
'c:\\music\\ap\\mahadeva.mp3'
>>> os.path.expanduser("~")
'c:\\Documents and Settings\\mpilgrim\\My Documents'
>>> os.path.join(os.path.expanduser("~"), "Python")
'c:\\Documents and Settings\\mpilgrim\\My Documents\\Python'
```
| | |
| --- | --- |
| \[1\] | `os.path` 是一個模塊的引用;使用哪一個模塊要看你正運行在哪種平臺上。就像 [`getpass`](index.html#crossplatform.example "例?6.2.?支持特定平臺功能") 通過將 `getpass` 設置為一個與平臺相關的函數從而封裝了平臺之間的不同。`os` 通過設置 `path` 封裝不同的相關平臺模塊。 |
| \[2\] | `os.path` 的 `join` 函數把一個或多個部分路徑名連接成一個路徑名。在這個簡單的例子中,它只是將字符串進行連接。(請注意在 Windows 下處理路徑名是一個麻煩的事,因為反斜線字符必須被轉義。) |
| \[3\] | 在這個幾乎沒有價值的例子中,在將路徑名加到文件名上之前,`join` 將在路徑名后添加額外的反斜線。當發現這一點時我高興極了,因為當用一種新的語言創建我自已的工具包時,`addSlashIfNecessary` 總是我必須要寫的那些愚蠢的小函數之一。在 Python 中_不要_ 寫這樣的愚蠢的小函數,聰明的人已經為你考慮到了。 |
| \[4\] | `expanduser` 將對使用 `~` 來表示當前用戶根目錄的路徑名進行擴展。在任何平臺上,只要用戶擁有一個根目錄,它就會有效,像 Windows、UNIX 和 Mac OS X,但在 Mac OS 上無效。 |
| \[5\] | 將這些技術組合在一起,你可以容易地為在用戶根目錄下的目錄和文件構造出路徑名。 |
## 例?6.17.?分割路徑名
```
>>> os.path.split("c:\\music\\ap\\mahadeva.mp3")
('c:\\music\\ap', 'mahadeva.mp3')
>>> (filepath, filename) = os.path.split("c:\\music\\ap\\mahadeva.mp3")
>>> filepath
'c:\\music\\ap'
>>> filename
'mahadeva.mp3'
>>> (shortname, extension) = os.path.splitext(filename)
>>> shortname
'mahadeva'
>>> extension
'.mp3'
```
| | |
| --- | --- |
| \[1\] | `split` 函數對一個全路徑名進行分割,返回一個包含路徑和文件名的 tuple。還記得我說過你可以使用[多變量賦值](../native_data_types/declaring_variables.html#odbchelper.multiassign "3.4.2.?一次賦多值")從一個函數返回多個值嗎?對,`split` 就是這樣一個函數。 |
| \[2\] | 我們將 `split` 函數的返回值賦值給一個兩個變量的 tuple。每個變量接收到返回 tuple 相對應的元素值。 |
| \[3\] | 第一個變量,`filepath`,接收到從 `split` 返回 tuple 的第一個元素的值,文件路徑。 |
| \[4\] | 第二個變量,`filename`,接收到從 `split` 返回 tuple 的第二個元素的值,文件名。 |
| \[5\] | `os.path` 也包含了一個 `splitext` 函數,可以用來對文件名進行分割,并且返回一個包含了文件名和文件擴展名的 tuple。我們使用相同的技術來將它們賦值給獨立的變量。 |
## 例?6.18.?列出目錄
```
>>> os.listdir("c:\\music\\_singles\\")
['a_time_long_forgotten_con.mp3', 'hellraiser.mp3',
'kairo.mp3', 'long_way_home1.mp3', 'sidewinder.mp3',
'spinning.mp3']
>>> dirname = "c:\\"
>>> os.listdir(dirname)
['AUTOEXEC.BAT', 'boot.ini', 'CONFIG.SYS', 'cygwin',
'docbook', 'Documents and Settings', 'Incoming', 'Inetpub', 'IO.SYS',
'MSDOS.SYS', 'Music', 'NTDETECT.COM', 'ntldr', 'pagefile.sys',
'Program Files', 'Python20', 'RECYCLER',
'System Volume Information', 'TEMP', 'WINNT']
>>> [f for f in os.listdir(dirname)
... if os.path.isfile(os.path.join(dirname, f))]
['AUTOEXEC.BAT', 'boot.ini', 'CONFIG.SYS', 'IO.SYS', 'MSDOS.SYS',
'NTDETECT.COM', 'ntldr', 'pagefile.sys']
>>> [f for f in os.listdir(dirname)
... if os.path.isdir(os.path.join(dirname, f))]
['cygwin', 'docbook', 'Documents and Settings', 'Incoming',
'Inetpub', 'Music', 'Program Files', 'Python20', 'RECYCLER',
'System Volume Information', 'TEMP', 'WINNT']
```
| | |
| --- | --- |
| \[1\] | `listdir` 函數接收一個路徑名,并返回那個目錄的內容的 list。 |
| \[2\] | `listdir` 同時返回文件和文件夾,并不指出哪個是文件,哪個是文件夾。 |
| \[3\] | 你可以使用[過濾列表](../power_of_introspection/filtering_lists.html "4.5.?過濾列表")和 `os.path` 模塊的 `isfile` 函數,從文件夾中將文件分離出來。`isfile` 接收一個路徑名,如果路徑表示一個文件,則返回 1,否則為 0。在這里,我們使用 ``os.path`.`join`` 來確保得到一個全路徑名,但 `isfile` 對部分路徑 (相對于當前目錄) 也是有效的。你可以使用 `os.getcwd()` 來得到當前目錄。 |
| \[4\] | `os.path` 還有一個 `isdir` 函數,當路徑表示一個目錄,則返回 1,否則為 0。你可以使用它來得到一個目錄下的子目錄列表。 |
## 例?6.19.?在 `fileinfo.py` 中列出目錄
```
def listDirectory(directory, fileExtList):
"get list of file info objects for files of particular extensions"
fileList = [os.path.normcase(f)
for f in os.listdir(directory)]
fileList = [os.path.join(directory, f)
for f in fileList
if os.path.splitext(f)[1] in fileExtList]
```
| | |
| --- | --- |
| \[1\] | `os.listdir(directory)` 返回在 `directory` 中所有文件和文件夾的一個 list。 |
| \[2\] | 使用 `f` 對 list 進行遍歷,我們使用 `os.path.normcase(f)` 根據操作系統的缺省值對大小寫進行標準化處理。`normcase` 是一個有用的函數,用于對大小寫不敏感操作系統的一個補充。這種操作系統認為 `mahadeva.mp3` 和 `mahadeva.MP3` 是同一個文件名。例如,在 Windows 和 Mac OS 下,`normcase` 將把整個文件名轉換為小寫字母;而在 UNIX 兼容的系統下,它將返回未作修改的文件名。 |
| \[3\] | 再次用 `f` 對標準化后的 list 進行遍歷,我們使用 `os.path.splitext(f)` 將每個文件名分割為名字和擴展名。 |
| \[4\] | 對每個文件,我們查看擴展名是否在我們關心的文件擴展名 list 中 (`fileExtList`,被傳遞給 `listDirectory` 函數)。 |
| \[5\] | 對每個我們所關心的文件,我們使用 `os.path.join(directory, f)` 來構造這個文件的全路徑名,接著返回這個全路徑名的 list。 |
> 注意
> 只要有可能,你就應該使用在 `os` 和 `os.path` 中的函數進行文件、目錄和路徑的操作。這些模塊是對平臺相關模塊的封裝模塊,所以像 `os.path.split` 這樣的函數可以工作在 UNIX、Windows、Mac OS 和 Python 所支持的任一種平臺上。
還有一種獲得目錄內容的方法。它非常強大,并使用了一些你在命令行上工作時可能已經熟悉的通配符。
## 例?6.20.?使用 `glob` 列出目錄
```
>>> os.listdir("c:\\music\\_singles\\")
['a_time_long_forgotten_con.mp3', 'hellraiser.mp3',
'kairo.mp3', 'long_way_home1.mp3', 'sidewinder.mp3',
'spinning.mp3']
>>> import glob
>>> glob.glob('c:\\music\\_singles\\*.mp3')
['c:\\music\\_singles\\a_time_long_forgotten_con.mp3',
'c:\\music\\_singles\\hellraiser.mp3',
'c:\\music\\_singles\\kairo.mp3',
'c:\\music\\_singles\\long_way_home1.mp3',
'c:\\music\\_singles\\sidewinder.mp3',
'c:\\music\\_singles\\spinning.mp3']
>>> glob.glob('c:\\music\\_singles\\s*.mp3')
['c:\\music\\_singles\\sidewinder.mp3',
'c:\\music\\_singles\\spinning.mp3']
>>> glob.glob('c:\\music\\*\\*.mp3')
```
| | |
| --- | --- |
| \[1\] | 正如你前面看到的,`os.listdir` 簡單地取一個目錄路徑,返回目錄中的所有文件和子目錄。 |
| \[2\] | `glob` 模塊,另一方面,接受一個通配符并且返回文件的或目錄的完整路徑與之匹配。這個通配符是一個目錄路徑加上“*.mp3”,它將匹配所有的 `.mp3` 文件。注意返回列表的每一個元素已經包含了文件的完整路徑。 |
| \[3\] | 如果你要查找指定目錄中所有以“s”開頭并以“.mp3”結尾的文件,也可以這么做。 |
| \[4\] | 現在考查這種情況:你有一個 `music` 目錄,它包含幾個子目錄,子目錄中包含一些 `.mp3` 文件。使用兩個通配符,僅僅調用 `glob` 一次就可以立刻獲得所有這些文件的一個 list。一個通配符是 `"*.mp3"` (用于匹配 `.mp3` 文件),另一個通配符是_子目錄名本身_,用于匹配 `c:\music` 中的所有子目錄。這看上去很簡單,但它蘊含了強大的功能。 |
## 進一步閱讀
* Python Knowledge Base 回答了[關于 `os` 模塊的問題](http://www.faqts.com/knowledge-base/index.phtml/fid/240)。
* _Python Library Reference_ 提供了 [`os`](http://www.python.org/doc/current/lib/module-os.html) 模塊和 [`os.path`](http://www.python.org/doc/current/lib/module-os.path.html) 模塊的文檔。
- 版權信息
- 第?1?章?安裝 Python
- 1.1.?哪一種 Python 適合您?
- 1.2.?Windows 上的 Python
- 1.3.?Mac OS X 上的 Python
- 1.4.?Mac OS 9 上的 Python
- 1.5.?RedHat Linux 上的 Python
- 1.6.?Debian GNU/Linux 上的 Python
- 1.7.?從源代碼安裝 Python
- 1.8.?使用 Python 的交互 Shell
- 1.9.?小結
- 第?2?章?第一個 Python 程序
- 2.1.?概覽
- 2.2.?函數聲明
- 2.3.?文檔化函數
- 2.4.?萬物皆對象
- 2.5.?代碼縮進
- 2.6.?測試模塊
- 第?3?章?內置數據類型
- 3.1.?Dictionary 介紹
- 3.2.?List 介紹
- 3.3.?Tuple 介紹
- 3.4.?變量聲明
- 3.5.?格式化字符串
- 3.6.?映射 list
- 3.7.?連接 list 與分割字符串
- 3.8.?小結
- 第?4?章?自省的威力
- 4.1.?概覽
- 4.2.?使用可選參數和命名參數
- 4.3.?使用 type、str、dir 和其它內置函數
- 4.4.?通過 getattr 獲取對象引用
- 4.5.?過濾列表
- 4.6.?and 和 or 的特殊性質
- 4.7.?使用 lambda 函數
- 4.8.?全部放在一起
- 4.9.?小結
- 第?5?章?對象和面向對象
- 5.1.?概覽
- 5.2.?使用 from _module_ import 導入模塊
- 5.3.?類的定義
- 5.4.?類的實例化
- 5.5.?探索 UserDict:一個封裝類
- 5.6.?專用類方法
- 5.7.?高級專用類方法
- 5.8.?類屬性介紹
- 5.9.?私有函數
- 5.10.?小結
- 第?6?章?異常和文件處理
- 6.1.?異常處理
- 6.2.?與文件對象共事
- 6.3.?for 循環
- 6.4.?使用 `sys.modules`
- 6.5.?與目錄共事
- 6.6.?全部放在一起
- 6.7.?小結
- 第?7?章?正則表達式
- 7.1.?概覽
- 7.2.?個案研究:街道地址
- 7.3.?個案研究:羅馬字母
- 7.4.?使用 {n,m} 語法
- 7.5.?松散正則表達式
- 7.6.?個案研究:解析電話號碼
- 7.7.?小結
- 第?8?章?HTML 處理
- 8.1.?概覽
- 8.2.?sgmllib.py 介紹
- 8.3.?從 HTML 文檔中提取數據
- 8.4.?BaseHTMLProcessor.py 介紹
- 8.5.?locals 和 globals
- 8.6.?基于 dictionary 的字符串格式化
- 8.7.?給屬性值加引號
- 8.8.?dialect.py 介紹
- 8.9.?全部放在一起
- 8.10.?小結
- 第?9?章?XML 處理
- 9.1.?概覽
- 9.2.?包
- 9.3.?XML 解析
- 9.4.?Unicode
- 9.5.?搜索元素
- 9.6.?訪問元素屬性
- 9.7.?Segue [9]
- 第?10?章?腳本和流
- 10.1.?抽象輸入源
- 10.2.?標準輸入、輸出和錯誤
- 10.3.?查詢緩沖節點
- 10.4.?查找節點的直接子節點
- 10.5.?根據節點類型創建不同的處理器
- 10.6.?處理命令行參數
- 10.7.?全部放在一起
- 10.8.?小結
- 第?11?章?HTTP Web 服務
- 11.1.?概覽
- 11.2.?避免通過 HTTP 重復地獲取數據
- 11.3.?HTTP 的特性
- 11.4.?調試 HTTP web 服務
- 11.5.?設置 User-Agent
- 11.6.?處理 Last-Modified 和 ETag
- 11.7.?處理重定向
- 11.8.?處理壓縮數據
- 11.9.?全部放在一起
- 11.10.?小結
- 第?12?章?SOAP Web 服務
- 12.1.?概覽
- 12.2.?安裝 SOAP 庫
- 12.3.?步入 SOAP
- 12.4.? SOAP 網絡服務查錯
- 12.5.?WSDL 介紹
- 12.6.?以 WSDL 進行 SOAP 內省
- 12.7.?搜索 Google
- 12.8.? SOAP 網絡服務故障排除
- 12.9.?小結
- 第?13?章?單元測試
- 13.1.?羅馬數字程序介紹 II
- 13.2.?深入
- 13.3.?romantest.py 介紹
- 13.4.?正面測試 (Testing for success)
- 13.5.?負面測試 (Testing for failure)
- 13.6.?完備性檢測 (Testing for sanity)
- 第?14?章?測試優先編程
- 14.1.?roman.py, 第 1 階段
- 14.2.?roman.py, 第 2 階段
- 14.3.?roman.py, 第 3 階段
- 14.4.?roman.py, 第 4 階段
- 14.5.?roman.py, 第 5 階段
- 第?15?章?重構
- 15.1.?處理 bugs
- 15.2.?應對需求變化
- 15.3.?重構
- 15.4.?后記
- 15.5.?小結
- 第?16?章?函數編程
- 16.1.?概覽
- 16.2.?找到路徑
- 16.3.?重識列表過濾
- 16.4.?重識列表映射
- 16.5.?數據中心思想編程
- 16.6.?動態導入模塊
- 16.7.?全部放在一起
- 16.8.?小結
- 第?17?章?動態函數
- 17.1.?概覽
- 17.2.?plural.py, 第 1 階段
- 17.3.?plural.py, 第 2 階段
- 17.4.?plural.py, 第 3 階段
- 17.5.?plural.py, 第 4 階段
- 17.6.?plural.py, 第 5 階段
- 17.7.?plural.py, 第 6 階段
- 17.8.?小結
- 第?18?章?性能優化
- 18.1.?概覽
- 18.2.?使用 timeit 模塊
- 18.3.?優化正則表達式
- 18.4.?優化字典查找
- 18.5.?優化列表操作
- 18.6.?優化字符串操作
- 18.7.?小結
- 附錄?A.?進一步閱讀
- 附錄?B.?五分鐘回顧
- 附錄?C.?技巧和竅門
- 附錄?D.?示例清單
- 附錄?E.?修訂歷史
- 附錄?F.?關于本書
- 附錄 G. GNU Free Documentation License
- G.0. Preamble
- G.1.?Applicability and definitions
- G.2.?Verbatim copying
- G.3.?Copying in quantity
- G.4.?Modifications
- G.5.?Combining documents
- G.6.?Collections of documents
- G.7.?Aggregation with independent works
- G.8.?Translation
- G.9.?Termination
- G.10.?Future revisions of this license
- G.11.?How to use this License for your documents
- 附錄 H. GNU 自由文檔協議
- H.0. 序
- H.1.?適用范圍和定義
- H.2.?原樣復制
- H.3.?大量復制
- H.4.?修改
- H.5.?合并文檔
- H.6.?文檔合集
- H.7.?獨立著作聚集
- H.8.?翻譯
- H.9.?終止協議
- H.10.?協議將來的修訂
- H.11.?如何為你的文檔使用本協議
- 附錄 I. Python license
- I.A. History of the software
- I.B.?Terms and conditions for accessing or otherwise using Python
- 附錄 J. Python 協議
- J.0. 關于譯文的聲明
- J.A.?軟件的歷史
- J.B.?使用 Python 的條款和條件