Python 目录操作
在Python编程中,操作文件系统目录是一项常见而重要的任务。无论是组织数据、管理文件,还是进行自动化操作,了解如何使用Python来操作目录都是必不可少的技能。本文将介绍Python中常用的目录操作函数和方法,帮助初学者掌握这一基本技能。
目录操作的基本模块
在Python中,主要通过以下模块来操作目录:
os
模块:提供了与操作系统交互的功能,包括目录和文件操作。os.path
模块:专门用于处理文件路径。shutil
模块:提供了更高级的文件和目录操作。pathlib
模块(Python 3.4+):提供了面向对象的文件系统路径处理方法。
让我们首先导入这些模块:
import os
import shutil
from pathlib import Path
获取当前工作目录
要获取当前的工作目录,我们可以使用os.getcwd()
函数:
current_dir = os.getcwd()
print(f"当前工作目录是: {current_dir}")
输出示例:
当前工作目录是: /Users/username/projects/python_tutorial
创建目录
使用os模块创建目录
使用os.mkdir()
可以创建一个新目录:
# 创建单个目录
try:
os.mkdir("new_folder")
print("目录创建成功!")
except FileExistsError:
print("目录已存在!")
如果需要创建多层次的目录结构,可以使用os.makedirs()
:
# 创建多层目录
try:
os.makedirs("parent_folder/child_folder/grandchild_folder")
print("多层目录创建成功!")
except FileExistsError:
print("目录已存在!")
使用pathlib模块创建目录
# 创建单个目录
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()
:
# 列出当前目录的内容
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()
,它提供了更多关于目录项的信息:
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模块列出目录内容
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模块
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模块
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()
:
# 先获取当前工作目录
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模块重命名
# 创建一个测试目录
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模块重命名
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模块删除
# 创建一个测试目录
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模块删除非空目录
# 创建一个嵌套的测试目录和文件
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模块删除
# 创建测试目录
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)
,表示所遍历的每个目录:
# 创建一些测试目录和文件
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模块遍历目录树
# 使用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:批量整理文件
假设我们有一个目录,里面混合了不同类型的文件,我们想按文件类型将它们整理到不同的子目录中:
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:备份目录
创建一个函数,用于将目录及其内容备份到指定位置:
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:查找符合特定模式的文件
创建一个函数,用于在目录及其子目录中查找符合特定模式的文件:
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进行目录操作,包括:
- 获取当前工作目录
- 创建单个和多层目录
- 列出目录内容
- 检查路径是否存在
- 修改工作目录
- 重命名目录
- 删除空目录和非空目录
- 遍历目录树
- 实际应用场景示例
掌握这些基本的目录操作技能对于编写文件处理脚本、数据整理工具或任何需要与文件系统交互的Python应用程序都至关重要。
练习
- 创建一个脚本,统计指定目录中各类型文件的数量。
- 编写一个函数,将给定目录中的所有文件按照修改日期排序,并输出结果。
- 创建一个"目录监控器",每隔一定时间检查指定目录的变化(新增、删除或修改的文件)。
- 实现一个简单的脚本,查找并删除给定目录中的所有空子目录。
- 开发一个工具,定期备份指定的重要目录,并保持最近5个备份版本。