1. 引言
在 Python 编程中,文件和目录操作是日常任务的基础。无论是读取配置文件、遍历日志文件,还是管理项目资源,都离不开对目录的获取和操作。Python 标准库提供了强大且易用的模块(如 os、pathlib)来帮助我们完成这些任务。本文将系统介绍在 Python 中获取目录的各种方法,从基础路径操作到高级遍历技巧,并附上详细的代码示例,帮助你高效处理文件系统任务。
2. 核心模块概览
Python 提供了两个主要的模块来处理目录和路径:
os模块 :传统的系统操作模块,提供了大量与操作系统交互的函数,如os.listdir()、os.walk()等。pathlib模块(Python 3.4+ 引入):面向对象的路径操作库,提供了更直观、更 Pythonic 的 API,推荐在新项目中使用。
3. 获取当前工作目录
当前工作目录(Current Working Directory, CWD)是 Python 脚本执行时所在的目录。获取它是许多文件操作的第一步。
使用 os.getcwd()
python
import os
current_dir = os.getcwd()
print(f"当前工作目录: {current_dir}")
# 输出示例: 当前工作目录: /home/user/projects
使用 pathlib.Path.cwd()
python
from pathlib import Path
current_dir = Path.cwd()
print(f"当前工作目录: {current_dir}")
# 输出示例: 当前工作目录: /home/user/projects
区别 :os.getcwd() 返回字符串,Path.cwd() 返回一个 Path 对象,后者可以直接调用更多方法(如 .parent、.joinpath())。
4. 列出目录内容
获取目录下的所有文件和子目录。
使用 os.listdir()
python
import os
path = "./data"
try:
entries = os.listdir(path)
print(f"目录 '{path}' 下的内容:")
for entry in entries:
print(f" - {entry}")
except FileNotFoundError:
print(f"目录 '{path}' 不存在")
使用 pathlib.Path.iterdir()
python
from pathlib import Path
path = Path("./data")
if path.exists() and path.is_dir():
print(f"目录 '{path}' 下的内容:")
for entry in path.iterdir():
print(f" - {entry.name}") # entry 是一个 Path 对象
else:
print(f"目录 '{path}' 不存在或不是目录")
注意 :os.listdir() 返回文件名(字符串)列表,而 path.iterdir() 返回 Path 对象生成器,后者可以更方便地获取文件属性。
5. 递归遍历目录树
当需要处理目录及其所有子目录时,递归遍历是必要的。
使用 os.walk()
os.walk() 是一个生成器,为每个目录返回一个三元组 (dirpath, dirnames, filenames)。
python
import os
root_dir = "./project"
for dirpath, dirnames, filenames in os.walk(root_dir):
print(f"正在访问目录: {dirpath}")
print(f" 子目录: {dirnames}")
print(f" 文件: {filenames}")
print("-" * 40)
使用 pathlib.Path.rglob() 和 glob()
Path.rglob(pattern) 递归匹配模式,Path.glob(pattern) 仅在当前目录匹配。
python
from pathlib import Path
# 递归查找所有 .py 文件
project_path = Path("./project")
py_files = list(project_path.rglob("*.py"))
print("所有 Python 文件:")
for py_file in py_files:
print(f" - {py_file}")
# 仅在当前目录查找 .txt 文件
txt_files = list(project_path.glob("*.txt"))
print("\n当前目录下的文本文件:")
for txt_file in txt_files:
print(f" - {txt_file}")
6. 获取目录的绝对路径
绝对路径是从根目录开始的完整路径,在不同环境下更可靠。
使用 os.path.abspath()
python
import os
relative_path = "./docs/readme.txt"
absolute_path = os.path.abspath(relative_path)
print(f"相对路径: {relative_path}")
print(f"绝对路径: {absolute_path}")
使用 pathlib.Path.resolve()
resolve() 方法会解析符号链接并返回绝对路径。
python
from pathlib import Path
relative_path = Path("./docs/readme.txt")
absolute_path = relative_path.resolve()
print(f"绝对路径: {absolute_path}")
7. 检查路径是否为目录
在操作前,最好先确认路径指向的是目录。
python
import os
from pathlib import Path
path_str = "./src"
path_obj = Path(path_str)
# 使用 os.path.isdir
if os.path.isdir(path_str):
print(f"'{path_str}' 是一个目录 (os)")
# 使用 Path.is_dir()
if path_obj.is_dir():
print(f"'{path_str}' 是一个目录 (pathlib)")
8. 创建与删除目录
创建目录
python
import os
from pathlib import Path
# 创建单个目录
os.makedirs("./new_dir", exist_ok=True) # exist_ok=True 避免目录已存在时报错
Path("./another_dir").mkdir(exist_ok=True)
# 创建多级目录(递归创建)
os.makedirs("./parent/child/grandchild", exist_ok=True)
Path("./deep/nested/path").mkdir(parents=True, exist_ok=True)
删除目录
python
import shutil
from pathlib import Path
# 删除空目录
try:
os.rmdir("./empty_dir")
except OSError as e:
print(f"删除失败: {e}")
# 删除非空目录(递归删除,危险!)
shutil.rmtree("./dir_with_content", ignore_errors=True)
# 使用 pathlib (需配合 shutil 删除非空目录)
target_dir = Path("./to_delete")
if target_dir.exists():
if target_dir.is_dir():
shutil.rmtree(target_dir)
9. 路径拼接与分解
安全地组合和拆分路径,避免手动字符串拼接。
使用 os.path.join()
python
import os
base = "/home/user"
subdir = "docs"
filename = "file.txt"
full_path = os.path.join(base, subdir, filename)
print(f"完整路径: {full_path}")
# 输出: /home/user/docs/file.txt
使用 pathlib.Path 的 / 操作符
python
from pathlib import Path
base = Path("/home/user")
full_path = base / "docs" / "file.txt"
print(f"完整路径: {full_path}")
# 输出: /home/user/docs/file.txt
# 获取父目录、文件名、后缀等
print(f"父目录: {full_path.parent}")
print(f"文件名: {full_path.name}")
print(f"后缀: {full_path.suffix}")
print(f"无后缀的文件名: {full_path.stem}")
10. 实战示例:统计目录下文件类型
结合以上知识,实现一个统计目录下各类文件数量的脚本。
python
from pathlib import Path
from collections import Counter
def analyze_directory(directory_path):
"""分析目录下文件的类型分布"""
path = Path(directory_path)
if not path.exists() or not path.is_dir():
print(f"错误: '{directory_path}' 不是有效目录")
return
extensions = []
for item in path.rglob("*"): # 递归遍历所有文件
if item.is_file():
ext = item.suffix.lower() or "无后缀"
extensions.append(ext)
if not extensions:
print("该目录下未找到文件。")
return
counter = Counter(extensions)
print(f"目录 '{directory_path}' 下的文件类型统计:")
for ext, count in counter.most_common():
print(f" {ext}: {count} 个文件")
# 使用示例
analyze_directory("./my_project")
11. 总结与最佳实践
- 优先使用
pathlib:对于新项目,pathlib提供了更清晰、更安全的 API。 - 处理异常 :文件系统操作可能失败(如权限不足、路径不存在),务必使用
try...except。 - 使用绝对路径:在脚本中处理关键路径时,使用绝对路径可以避免因工作目录变化导致的错误。
- 递归操作需谨慎 :使用
shutil.rmtree()或rglob()时,确保目标路径正确,避免误删。 - 跨平台兼容性 :使用
os.path.join()或pathlib的路径操作符可以确保路径分隔符在不同操作系统(Windows/Linux/macOS)上正确工作。
通过掌握这些方法,你可以轻松地在 Python 中完成各种目录获取和操作任务,为更复杂的文件处理工作打下坚实基础。