今天看了os和os.path模块的官方文档,其中os.rename()和os.renames()刚开始没有整明白到底啥区别,接着自己点进去看源码,再结合了几篇技术博客和实践,算是对于os.rename和os.renames的使用有了基本了解,特地纪录下,方便日后查看。如果有理解不当的地方,还请大家指出交流。
os.rename(src, dst, *, src_dir_fd=None, dst_dir_fd=None)
Rename the file or directory src to dst. If dst exists, the operation will fail with an OSError subclass in a number of cases.
os.renames(old, new)
Recursive directory or file renaming function. Works like rename(), except creation of any intermediate directories needed to make the new pathname good is attempted first. After the rename, directories corresponding to rightmost path segments of the old name will be pruned away using removedirs().
注解 This function can fail with the new directory structure made if you lack permissions needed to remove the leaf directory or file.
看完英文文档,一开始还是不明白os.renames()到底怎么递归,怎么用的。
接下来看看源码,发现os.renames调用rename(),只不过在调用之前,用的是makedirs()递归创建目录。所以本质上os.renames()应该是通过makedirs()来实现递归的。
def renames(old, new):
head, tail = path.split(new)
if head and tail and not path.exists(head):
makedirs(head)
rename(old, new)
head, tail = path.split(old)
if head and tail:
try:
removedirs(head)
except OSError:
pass
再说用法前,为了方便表述准确,我们学习一下os.path.split()
方法
看源码:
def split(p):
"""Split a pathname.
Return tuple (head, tail) where tail is everything after the final slash.
Either part may be empty."""
p = os.fspath(p)
seps = _get_bothseps(p)
d, p = splitdrive(p)
# set i to index beyond p's last slash
i = len(p)
while i and p[i-1] not in seps:
i -= 1
head, tail = p[:i], p[i:] # now tail has no slashes
# remove trailing slashes from head, unless it's all slashes
head = head.rstrip(seps) or head
return d + head, tail
官方说明:
翻译过来就是说,os.path.split()的功能是把给定的一个路径pathname,以最后一个斜线作为分分隔符,得到一个(head, tail),即(头, 尾)的元组。
>>> import os
>>> os.path.split('C:/a/b/c.text')
('C:/a/b', 'c.text')
>>> os.path.split('C:/a/b')
('C:/a', 'b')
>>> os.path.split('C:/a/')
('C:/a', '')
>>> os.path.split('c.text')
('', 'c.text')
>>> os.path.split('')
('', '')
理解了os.path.split()的用法,明确了head和tail的概念,接下来我们就进入os.rename()和os.path.renames()用法上的比较:
oldpath(oldhead, oldtail)
newpath(newhead, newtail)
对于os.rename(oldpath, newpath)而言,它的功能本质是有点像把文件oldtail(文件夹或者文件均可)移到newhead文件夹下并重命名为newtail(文件或者文件夹)
。它只可以更改oldtail部分,不能更改oldhead部分,即不可以更改上级目录部分。
示例:C:\Users\Jock\Desktop\test\1.jpg
# 重命名test文件夹 为test_a
>>> os.rename(r'C:\Users\Jock\Desktop\test', r'C:\Users\Jock\Desktop\test_a')
# 重命名1.jpg文件为2.jpg
>>> os.rename(r'C:\Users\Jock\Desktop\test_a\1.jpg', r'C:\Users\Jock\Desktop\test_a\2.jpg')
# newhead不存在,报错:FileNotFoundError: [WinError 3] 系统找不到指定的路径。
>>> os.rename(r'C:\Users\Jock\Desktop\test_a\2.jpg', r'C:\Users\Jock\Desktop\test_b\2.jpg')
FileNotFoundError: [WinError 3] 系统找不到指定的路径。: 'C:\\Users\\Jock\\Desktop\\test_a\\2.jpg' -> 'C:\\Users\\Jock\\Desktop\\test_b\\2.jpg'
# oldhead不存在,报错:FileNotFoundError: [WinError 3] 系统找不到指定的路径。
>>> os.rename(r'C:\Users\Jock\Desktop\test\2.jpg', r'C:\Users\Jock\Desktop\test_a\1.jpg')
FileNotFoundError: [WinError 3] 系统找不到指定的路径。: 'C:\\Users\\Jock\\Desktop\\test\\2.jpg' -> 'C:\\Users\\Jock\\Desktop\\test_a\\1.jpg'
# oldhead存在,oldtail不存在时,报错:FileNotFoundError: [WinError 2] 系统找不到指定的文件
>>> os.rename(r'C:\Users\Jock\Desktop\test_a\2.jpg', r'C:\Users\Jock\Desktop\test_a\1.jpg')
FileNotFoundError: [WinError 2] 系统找不到指定的文件。: 'C:\\Users\\Jock\\Desktop\\test_a\\2.jpg' -> 'C:\\Users\\Jock\\Desktop\\test_a\\1.jpg'
# 重新复制一张1.jpg文件到C:\Users\Jock\Desktop\test_a路径下,现在test_a包含1.jpg和2.jpg
# newhead存在,newtail存在,会报错:FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件
>>> os.rename(r'C:\Users\Jock\Desktop\test_a\1.jpg', r'C:\Users\Jock\Desktop\test_a\2.jpg')
FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。: 'C:\\Users\\Jock\\Desktop\\test_a\\1.jpg' -> 'C:\\Users\\Jock\\Desktop\\test_a\\2.jpg'
oldpath(oldhead, oldtail)
newpath(newhead, newtail)
对于os.renames(oldpath, newpath)而言,它可以只更改oldtail部分,也可以只更改oldhead部分,还可以同时更改oldhead和oldtail,对于newpath的newhead没有限制,只要有权限访问,如果newhead不存在,直接创建。
示例:C:\Users\Jock\Desktop\test\1.jpg
# 重命名test文件夹 为test_a
>>> os.renames(r'C:\Users\Jock\Desktop\test', r'C:\Users\Jock\Desktop\test_a')
# 重命名1.jpg文件为2.jpg
>>> os.renames(r'C:\Users\Jock\Desktop\test_a\1.jpg', r'C:\Users\Jock\Desktop\test_a\2.jpg')
# newhead不存在,直接创建newhead然后重命名,这里相当于修改了目录,文件名没有变
>>> os.renames(r'C:\Users\Jock\Desktop\test_a\2.jpg', r'C:\Users\Jock\Desktop\test_b\2.jpg')
# 同时修改目录和文件名
>>> os.renames(r'C:\Users\Jock\Desktop\test_b\2.jpg', r'C:\Users\Jock\Desktop\test_a\1.jpg')
# 如果oldhead不存在,会报错:FileNotFoundError: [WinError 3] 系统找不到指定的路径。
>>> os.renames(r'C:\Users\Jock\Desktop\test_b\1.jpg', r'C:\Users\Jock\Desktop\test_a\1.jpg')
FileNotFoundError: [WinError 3] 系统找不到指定的路径。: 'C:\\Users\\Jock\\Desktop\\test_b\\1.jpg' -> 'C:\\Users\\Jock\\Desktop\\test_a\\1.jpg'
# oldhead存在,oldtail不存在时,报错:FileNotFoundError: [WinError 2] 系统找不到指定的文件
>>> os.renames(r'C:\Users\Jock\Desktop\test_a\2.jpg', r'C:\Users\Jock\Desktop\test_a\1.jpg')
FileNotFoundError: [WinError 2] 系统找不到指定的文件。: 'C:\\Users\\Jock\\Desktop\\test_a\\2.jpg' -> 'C:\\Users\\Jock\\Desktop\\test_a\\1.jpg'
# 重新复制一张1.jpg文件到C:\Users\Jock\Desktop\test_a路径下,现在test_a包含1.jpg和2.jpg
# 如果newhead存在,newtail存在,会报错:FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件
>>> os.renames(r'C:\Users\Jock\Desktop\test_a\1.jpg', r'C:\Users\Jock\Desktop\test_a\2.jpg')
Traceback (most recent call last):
FileExistsError: [WinError 183] 当文件已存在时,无法创建该文件。: 'C:\\Users\\Jock\\Desktop\\test_a\\1.jpg' -> 'C:\\Users\\Jock\\Desktop\\test_a\\2.jpg'
后记:
我从本硕药学零基础转行计算机,自学路上,走过很多弯路,也庆幸自己喜欢记笔记,把知识点进行总结,帮助自己成功实现转行。
如果想和我一起交流学习,欢迎大家关注我的微信公众号No Bug编程笔记
,通过扫描下方二维码或者搜索NoBugNotes
关注。这个公众号主要是分享和记录自己学习编程的笔记,如:C – > Python – > Java等,后续还会分享自己面试以及职场上的成长心得。