本文通过代码将OS模块中的常用方法以案例的方式展现出来,方便大家查阅
创建文件及目录
python
import os
# 导入模块
print(os.getcwd())
# 输出当前路径
path = r"C:\Users\Nexus_16_MLK\Desktop"
dirname = "test_dir"
os.chdir(path)
# 切换到指定路径
print(os.getcwd())
os.mkdir(dirname)
# 创建文件夹
上面这串代码在桌面创建了文件夹,我们可以在桌面上找到该文件夹并打开。其中用os.mkdir()方法创建目录时,所有的父目录都必须存在。也就是说它无法直接创建多级文件夹,比如我们把上面的os.mkdir(dirname)换成os.mkdir(r"test\123")程序就会报错
因此如果我们要用os.mkdir()方法创建目录前,必须要用os.chdir()方法切换到指定目录
如果我们不想进行复杂的切换,我们可以直接使用makedirs()方法直接创建父目录,也就是将代码改成下面这样
python
import os
# 导入模块
path = r"C:\Users\Nexus_16_MLK\Desktop"
os.makedirs(rf"{path}\test\123")
# 创建多级文件夹
要注意不是mkdirs(),是makedirs()
查阅和筛选文件
在我们创建完目录后,我们可以对整个文件路径进行查阅
python
import os
# 导入模块
path = r"C:\Users\Nexus_16_MLK\Desktop"
print(os.listdir(path))
# 输出路径下所有文件名及目录名,包含隐藏文件,不包含子目录和子文件
with open(rf"{path}\result.txt", "w", encoding="utf-8") as f:
for dirname, subdirs, files in os.walk(path):
f.write(f"{dirname}\n{subdirs}\n{files}\n")
# 对给定路径下的文件进行遍历,生成(当前遍历路径,遍历路径下的子目录,遍历路径下的文件)样式的元组,子目录和子文件以列表形式返回
for entry in os.scandir(path):
# 和os.listdir()效果一样,返回指定目录下的所有文件和目录名,返回的是一个迭代器
if entry.is_dir():
tye = "dir"
elif entry.is_file():
tye = "file"
elif entry.is_symlink():
tye = "symlink"
else:
tye = "unknown"
print(f"{entry.name:<75}{tye}")
# 输出文件名和类型
os.listdir()和os.scandir()功能一样,都是遍历指定路径并返回目录和文件名,但os.scandir()方法返回的是一个迭代器,相比于os.listdir()这样一次性返回的方式,os.scandir()更节省内存,因此也更推荐使用
os.walk()的遍历顺序是从给定路径------>第一个文件------>第一个文件子目录------>第一个文件中所有的目录遍历完后遍历下一个------>继续遍历
os.walk()也可以指定遍历的路径
python
import os
# 导入模块
path = r"C:\Users\Nexus_16_MLK\Desktop"
for root, dirs, files in os.walk(path):
# 排除所有以点开头的隐藏目录和名为node_modules的目录
dirs[:] = [d for d in dirs if not d.startswith('.') and d != 'node_modules']
print(dirs)
我们也可以对文件目录进行更高级的操作,比如筛选出指定类型的文件,或者是批量重命名等
python
import os
# 导入模块
path = r"C:\Users\Nexus_16_MLK\Desktop"
for root, dirs, files in os.walk(path):
for f in files:
if f.endswith(".py"):
print(os.path.join(root, f))
# 输出给定文件路径下所有py文件的位置
o_str = "old_str"
# 搜索的字符串
n_str = "new_str"
# 要替换成的字符串
for root, dirs, files in os.walk(path):
for filename in files:
if o_str in filename:
# 检查文件名中是否包含指定字符串
new_filename = filename.replace(o_str, n_str)
old_path = os.path.join(root, filename)
new_path = os.path.join(root, new_filename)
# 构造完整路径
try:
os.rename(old_path, new_path)
# 进行重命名
print(f"成功: {old_path} -> {new_path}")
except OSError as e:
print(f"失败: 无法重命名 {old_path}, 错误: {e}")
我们使用os.rename(src, dst)进行了重命名操作,要注意重命名的文件名不能是已经存在的
读取文件具体信息
如果要读取文件的具体信息,我们需要用到os.stat()方法
python
import os
import time
# 导入模块
path = r"C:\Users\Nexus_16_MLK\Desktop"
with open(rf"{path}\test\test.txt", "w") as f:
f.write("test")
stat_info = os.stat(rf"{path}\test\test.txt")
print("size:",stat_info.st_size)
# 文件大小
print("premission:",stat_info.st_mode)
# 文件权限,33206代表普通文件可读写,33060代表普通文件只读,16895代表目录完全控制,16749代表目录只读
print("owner:",stat_info.st_uid)
# 所属用户
print("device:",stat_info.st_dev)
# 所属设备
print("last modified:",time.ctime(stat_info.st_mtime))
# 最后修改时间
print("last access:",time.ctime(stat_info.st_atime))
# 最后访问时间
我们也可以对文件权限进行修改,修改有两种方式,一种是用os.chmod()方法,另一种是用stat模块
python
import os
import stat
# 导入模块
path = r"C:\Users\Nexus_16_MLK\Desktop"
os.chmod(rf"{path}\test\test.txt", 33060)
# 改成只读
os.chmod(rf"{path}\test\test.txt", stat.S_IWUSR)
# 改成可写
使用stat可读性会比单用数字代码更高,主要有S_IRUSR(读), S_IWUSR(写), S_IXUSR(执行), S_IRWXU(全部)四种文件权限
文件的重命名和替换
我们之前用os.rename()对文件进行过重命名,除了os.renmae()之外,我们还有os.replace()这个方法可以用来对文件进行重命名
python
import os
# 导入模块
path = r"C:\Users\Nexus_16_MLK\Desktop\test"
with open(rf"{path}\test2.txt", "w") as f:
f.write("test2")
# os.rename(rf"{path}\test.txt", rf"{path}\test2.txt")
# 报错FileExistsError
os.replace(rf"{path}\test.txt", rf"{path}\test2.txt")
# replace方法遇到同名文件会直接进行覆盖
# os.rename(rf"{path}\test.txt", rf"{path}\test1\test1.txt")
# os.replace(rf"{path}\test.txt", rf"{path}\test1\test1.txt")
# 当我们想将文件移动到没有创建的子文件夹时,会引发FileNotFoundError
文件的删除
了解了文件的创建、查阅、修改,最后我们来看看文件的删除
python
import os
# 导入模块
path = r"C:\Users\Nexus_16_MLK\Desktop\test"
os.makedirs(rf"{path}\t1\t2")
with open(rf"{path}\t1\t2\1.txt", "w", encoding="utf-8") as f:
f.write("1111111")
os.remove(rf"{path}\t1\t2\1.txt")
# 删除单个文件,无法删除目录
os.rmdir(rf"{path}\t1\t2")
# 删除没有子文件夹和子文件的空目录
os.removedirs(rf"{path}\t1")
# 递归删除空目录,先删除t1, 然后删除test
在进行删除操作时,我们要注意,os模块中不支持删除非空的目录,如果需要删除有文件的整个文件夹,我们需要用到shutil模块中的rmtree()方法
同时,当我们用os.remove()方法删除文件时,要注意,文件会被直接抹除,不会进回收站
优化文件路径
在上面的代码中,我们用path = r"C:\Users\Nexus_16_MLK\Desktop\test"来给定路径,但是这种用字符串加反斜杠的方式写出路径,存在着很多缺点和隐患(比如斜杠在windows上是\在linux上是/),所以我们要用os.path对路径的写法进行优化
python
import os
path = r"C:\Users\Nexus_16_MLK\Desktop\z\1.txt"
filename, extension = os.path.splitext(path)
# 对文件名和后缀名进行分离
print(filename)
print(extension)
dir_path, full_name = os.path.split(path)
# 对路径和文件名进行分离
print(dir_path)
print(full_name)
new_path = os.path.join("C:\\", "Users", "Nexus_16_MLK", "Desktop", "z", full_name)
# join方法可以自动在不同系统转换路径分隔符
# 在windows上驱动器号后面的斜杠最好自己补充,注意尽量不要在第二个参数前加斜杠
print(new_path)
print(os.path.exists(new_path))
# 路径是否存在?
print(os.path.isfile(new_path))
# 是文件吗?(如果是目录会返回 False)
print(os.path.isdir(new_path))
# 是目录吗?
print(os.path.isabs(new_path))
# 是绝对路径吗?
print(os.path.basename(new_path))
# 只要最后的文件名+后缀,省略前面路径
print(os.path.dirname(new_path))
# 只要前面路径,不要文件名和后缀
print(os.path.islink(new_path))
# 判断是不是软链接(路径重定向,不是快捷方式)
print(os.path.samefile(new_path, path))
# 判断是不是同一个文件
软链接
我们刚才提到了软链接,软链接的本质是磁盘内的索引,当我们把路径A软链接到路径B,当我们访问路径A时会直接跳转到路径B,而快捷方式的本质是一个能快速执行对应文件的二进制.lnk文件。
我们可以通过下面的图表看到它们之间的差异

我们也可以用代码的方式更直观地了解软链接,我们可以通过os.symlink()方式来创建软链接
python
import os
path = os.path.join("C:\\", "Users", "Nexus_16_MLK", "Desktop", "z")
with open(rf"{path}\1.txt", "w", encoding="utf-8") as f:
f.write("1")
os.symlink(rf"{path}\1.txt", rf"{path}\2.txt")
# 2.txt不能是已经存在的,创建软链接是通过1.txt去创建一个分身2.txt
with open(rf"{path}\2.txt", "r", encoding="utf-8") as f:
print(f.read())
print(os.path.islink(rf"{path}\2.txt"))
# 判断是否为软链接
print(os.path.realpath(rf"{path}\2.txt"))
# 输出软链接指向的真实文件
print(os.path.samefile(rf"{path}\1.txt", rf"{path}\2.txt"))
# 本质上它们就是同一个文件
创建软链接后,我们对其中一个文件进行修改,另一个文件也会改变,其实它们就是一个文件
那很多人会问,它们本质上是一个文件,那这软链接有什么意义呢?
- 软链接最重要最核心的就是节省空间,当一对一时,作用不是很大,但是当几十个上百个文件都可以链接到一份文件上,节省的空间是非常大的
- 目录结构和路径编码,当有些文件写死在某个目录下时,我们可以通过软链接的方式,让死的目录结构变得灵活起来
- 热更新\热切换。当我们对某些文件进行版本更新时,我们不用更新文件,而是更新最初设置的软链接的指向(删除旧的再创建新的,这过程中只会删除链接,不会动到文件),让它从旧文件指向新文件即可实现无缝切换