# 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 的条款和条件