跳到主要内容

Python 目录操作

在Python编程中,操作文件系统目录是一项常见而重要的任务。无论是组织数据、管理文件,还是进行自动化操作,了解如何使用Python来操作目录都是必不可少的技能。本文将介绍Python中常用的目录操作函数和方法,帮助初学者掌握这一基本技能。

目录操作的基本模块

在Python中,主要通过以下模块来操作目录:

  • os 模块:提供了与操作系统交互的功能,包括目录和文件操作。
  • os.path 模块:专门用于处理文件路径。
  • shutil 模块:提供了更高级的文件和目录操作。
  • pathlib 模块(Python 3.4+):提供了面向对象的文件系统路径处理方法。

让我们首先导入这些模块:

python
import os
import shutil
from pathlib import Path

获取当前工作目录

要获取当前的工作目录,我们可以使用os.getcwd()函数:

python
current_dir = os.getcwd()
print(f"当前工作目录是: {current_dir}")

输出示例:

当前工作目录是: /Users/username/projects/python_tutorial

创建目录

使用os模块创建目录

使用os.mkdir()可以创建一个新目录:

python
# 创建单个目录
try:
os.mkdir("new_folder")
print("目录创建成功!")
except FileExistsError:
print("目录已存在!")

如果需要创建多层次的目录结构,可以使用os.makedirs()

python
# 创建多层目录
try:
os.makedirs("parent_folder/child_folder/grandchild_folder")
print("多层目录创建成功!")
except FileExistsError:
print("目录已存在!")

使用pathlib模块创建目录

python
# 创建单个目录
p = Path("new_folder_pathlib")
p.mkdir(exist_ok=True)
print(f"目录 {p} 创建成功或已存在")

# 创建多层目录
p = Path("parent/child/grandchild")
p.mkdir(parents=True, exist_ok=True)
print(f"多层目录 {p} 创建成功或已存在")
提示

使用exist_ok=True参数可以避免目录已存在时抛出异常,这是一个很实用的技巧。

列出目录内容

使用os模块列出目录内容

要列出目录中的所有文件和子目录,我们可以使用os.listdir()

python
# 列出当前目录的内容
files_and_dirs = os.listdir()
print("当前目录内容:")
for item in files_and_dirs:
print(f" - {item}")

# 列出指定目录的内容
specified_dir = "new_folder"
if os.path.exists(specified_dir):
files_and_dirs = os.listdir(specified_dir)
print(f"{specified_dir}目录内容:")
for item in files_and_dirs:
print(f" - {item}")

使用os.scandir()进行高级列表操作

Python 3.5引入了os.scandir(),它提供了更多关于目录项的信息:

python
with os.scandir() as entries:
for entry in entries:
file_type = "文件" if entry.is_file() else "目录" if entry.is_dir() else "其他"
print(f"{entry.name}: {file_type}")

使用pathlib模块列出目录内容

python
p = Path(".")
print("使用pathlib列出当前目录内容:")
for item in p.iterdir():
item_type = "文件" if item.is_file() else "目录" if item.is_dir() else "其他"
print(f" - {item.name}: {item_type}")

检查路径是否存在

在进行目录操作之前,通常需要检查路径是否存在:

使用os.path模块

python
path_to_check = "new_folder"

# 检查路径是否存在
if os.path.exists(path_to_check):
print(f"{path_to_check} 存在")

# 检查是否是目录
if os.path.isdir(path_to_check):
print(f"{path_to_check} 是一个目录")

# 检查是否是文件
if os.path.isfile(path_to_check):
print(f"{path_to_check} 是一个文件")
else:
print(f"{path_to_check} 不存在")

使用pathlib模块

python
p = Path("new_folder")

if p.exists():
print(f"{p} 存在")

if p.is_dir():
print(f"{p} 是一个目录")

if p.is_file():
print(f"{p} 是一个文件")
else:
print(f"{p} 不存在")

修改工作目录

要更改当前的工作目录,可以使用os.chdir()

python
# 先获取当前工作目录
original_dir = os.getcwd()
print(f"原工作目录: {original_dir}")

# 修改工作目录
try:
os.chdir("new_folder")
print(f"已修改工作目录至: {os.getcwd()}")

# 执行一些操作...

# 最后切回原目录
os.chdir(original_dir)
print(f"已切回原工作目录: {os.getcwd()}")
except FileNotFoundError:
print("目录不存在,无法切换")

重命名目录

使用os模块重命名

python
# 创建一个测试目录
if not os.path.exists("old_name"):
os.mkdir("old_name")
print("创建测试目录 old_name")

# 重命名目录
try:
os.rename("old_name", "new_name")
print("目录已重命名为 new_name")
except FileExistsError:
print("目标名称已存在,无法重命名")
except FileNotFoundError:
print("源目录不存在,无法重命名")

使用pathlib模块重命名

python
old_path = Path("old_name_pathlib")
new_path = Path("new_name_pathlib")

# 创建测试目录
if not old_path.exists():
old_path.mkdir()
print(f"创建测试目录 {old_path}")

# 重命名目录
try:
old_path.rename(new_path)
print(f"目录已重命名为 {new_path}")
except FileExistsError:
print("目标名称已存在,无法重命名")

删除目录

使用os模块删除

python
# 创建一个测试目录
if not os.path.exists("to_delete"):
os.mkdir("to_delete")
print("创建测试目录 to_delete")

# 删除空目录
try:
os.rmdir("to_delete")
print("目录 to_delete 已删除")
except FileNotFoundError:
print("目录不存在,无法删除")
except OSError:
print("目录不为空,无法使用os.rmdir()删除")

使用shutil模块删除非空目录

python
# 创建一个嵌套的测试目录和文件
nested_dir = "nested_to_delete"
if not os.path.exists(nested_dir):
os.makedirs(os.path.join(nested_dir, "subdir"))
with open(os.path.join(nested_dir, "test.txt"), "w") as f:
f.write("测试文件")
print(f"创建嵌套测试目录和文件 {nested_dir}")

# 删除非空目录及其所有内容
try:
shutil.rmtree(nested_dir)
print(f"目录 {nested_dir} 及其所有内容已删除")
except FileNotFoundError:
print("目录不存在,无法删除")
警告

shutil.rmtree()会删除指定目录及其所有内容,使用时要非常小心。它不会将文件移至回收站,而是直接永久删除。

使用pathlib模块删除

python
# 创建测试目录
p = Path("to_delete_pathlib")
if not p.exists():
p.mkdir()
print(f"创建测试目录 {p}")

# 删除空目录
try:
p.rmdir()
print(f"目录 {p} 已删除")
except FileNotFoundError:
print("目录不存在,无法删除")

遍历目录树

在处理复杂的目录结构时,我们通常需要遍历整个目录树。

使用os.walk()遍历

os.walk()生成一个三元组(dirpath, dirnames, filenames),表示所遍历的每个目录:

python
# 创建一些测试目录和文件
test_structure = "test_walk"
if not os.path.exists(test_structure):
os.makedirs(os.path.join(test_structure, "subdir1"))
os.makedirs(os.path.join(test_structure, "subdir2"))
with open(os.path.join(test_structure, "file1.txt"), "w") as f:
f.write("文件1")
with open(os.path.join(test_structure, "subdir1", "file2.txt"), "w") as f:
f.write("文件2")
print(f"创建测试目录结构 {test_structure}")

# 遍历目录树
print(f"\n遍历 {test_structure} 目录树:")
for dirpath, dirnames, filenames in os.walk(test_structure):
print(f"当前目录: {dirpath}")

if dirnames:
print(" 子目录:", ", ".join(dirnames))

if filenames:
print(" 文件:", ", ".join(filenames))

print() # 空行,增加可读性

使用pathlib模块遍历目录树

python
# 使用pathlib递归遍历目录
def walk_pathlib(path):
p = Path(path)
print(f"当前目录: {p}")

dirs = [d for d in p.iterdir() if d.is_dir()]
files = [f for f in p.iterdir() if f.is_file()]

if dirs:
print(f" 子目录: {', '.join(str(d.name) for d in dirs)}")

if files:
print(f" 文件: {', '.join(str(f.name) for f in files)}")

print() # 空行

for d in dirs:
walk_pathlib(d)

# 执行遍历
print(f"\n使用pathlib遍历 {test_structure} 目录树:")
walk_pathlib(test_structure)

实际应用场景

让我们来看一些目录操作的实际应用场景:

场景1:批量整理文件

假设我们有一个目录,里面混合了不同类型的文件,我们想按文件类型将它们整理到不同的子目录中:

python
import os
from pathlib import Path
import shutil

def organize_files(directory):
"""按文件类型整理目录中的文件"""
# 确保目录存在
if not os.path.exists(directory):
print(f"目录 {directory} 不存在!")
return

# 获取目录中的所有文件
files = [f for f in os.listdir(directory) if os.path.isfile(os.path.join(directory, f))]

if not files:
print(f"目录 {directory} 中没有文件!")
return

# 按文件扩展名分类
for file in files:
# 获取文件扩展名
file_path = os.path.join(directory, file)
extension = os.path.splitext(file)[1][1:].lower() # 去掉点并转为小写

if not extension: # 如果没有扩展名
extension = "no_extension"

# 创建对应的子目录
extension_dir = os.path.join(directory, extension)
if not os.path.exists(extension_dir):
os.mkdir(extension_dir)
print(f"创建目录: {extension_dir}")

# 移动文件
destination = os.path.join(extension_dir, file)
shutil.move(file_path, destination)
print(f"移动: {file} -> {extension}/{file}")

# 使用示例
# organize_files("my_files")

场景2:备份目录

创建一个函数,用于将目录及其内容备份到指定位置:

python
import os
import shutil
import datetime

def backup_directory(source, destination=None):
"""备份目录及其内容"""
# 检查源目录是否存在
if not os.path.exists(source):
print(f"源目录 {source} 不存在!")
return

# 如果没有指定目标位置,则在当前目录创建备份
if destination is None:
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
base_name = os.path.basename(source)
destination = f"{base_name}_backup_{timestamp}"

# 创建备份
try:
shutil.copytree(source, destination)
print(f"成功将 {source} 备份到 {destination}")
except Exception as e:
print(f"备份失败: {e}")

# 使用示例
# backup_directory("important_data")

场景3:查找符合特定模式的文件

创建一个函数,用于在目录及其子目录中查找符合特定模式的文件:

python
import os
import fnmatch

def find_files(directory, pattern):
"""在目录及其子目录中查找符合模式的文件"""
matches = []

for root, dirnames, filenames in os.walk(directory):
for filename in fnmatch.filter(filenames, pattern):
matches.append(os.path.join(root, filename))

return matches

# 使用示例
# 查找所有.py文件
# python_files = find_files(".", "*.py")
# print(f"找到 {len(python_files)} 个Python文件:")
# for file in python_files:
# print(f" - {file}")

总结

在本文中,我们学习了如何使用Python进行目录操作,包括:

  1. 获取当前工作目录
  2. 创建单个和多层目录
  3. 列出目录内容
  4. 检查路径是否存在
  5. 修改工作目录
  6. 重命名目录
  7. 删除空目录和非空目录
  8. 遍历目录树
  9. 实际应用场景示例

掌握这些基本的目录操作技能对于编写文件处理脚本、数据整理工具或任何需要与文件系统交互的Python应用程序都至关重要。

练习

  1. 创建一个脚本,统计指定目录中各类型文件的数量。
  2. 编写一个函数,将给定目录中的所有文件按照修改日期排序,并输出结果。
  3. 创建一个"目录监控器",每隔一定时间检查指定目录的变化(新增、删除或修改的文件)。
  4. 实现一个简单的脚本,查找并删除给定目录中的所有空子目录。
  5. 开发一个工具,定期备份指定的重要目录,并保持最近5个备份版本。

延伸资源