我想将文件src
复制到目标dst
,但如果src
恰好是符号链接,请保留链接,而不是复制文件内容。执行复制后,os.readlink
应为src
和dst
返回相同内容。
模块shutil
有几个功能,例如copyfile
,copy
和copy2
,但所有这些功能都会复制内容该文件,并不会保留链接。 shutil.move
具有正确的行为,除了删除原始文件的事实。
Python中是否有内置的方法来执行文件复制,同时保留符号链接?
答案 0 :(得分:42)
只做
def copy(src, dst):
if os.path.islink(src):
linkto = os.readlink(src)
os.symlink(linkto, dst)
else:
shutil.copy(src,dst)
shutil.copytree做了类似的事情,但正如发送者指出的那样,只复制目录而不是单个文件是挑剔的。
答案 1 :(得分:0)
Python 3 follow_symlinks
在Python 3中,大多数shutil
的复制方法都学会了follow_symlinks
参数,该参数保留了被选中的符号链接。
例如为shutil.copy
:
shutil.copy(src, dest, follow_symlinks=False)
shutil.copy(src, dst, *, follow_symlinks=True)
将文件src复制到文件或目录dst。 src和dst应该是字符串。如果dst指定目录,则将使用src中的基本文件名将文件复制到dst中。返回新创建文件的路径。
如果
follow_symlinks
为false,并且src是符号链接,则将dst创建为符号链接。如果follow_symlinks`为true,并且src是符号链接,则dst将是src引用的文件的副本。
但是,这有一个问题:如果您尝试覆盖现有文件或符号链接,它将失败并显示以下信息:
FileExistsError: [Errno 17] File exists: 'b' -> 'c'
不同于follow_symlinks=True
会成功覆盖。
os.symlink
也会发生同样的情况,所以我最终改为使用:
#!/usr/bin/env python3
import shutil
import os
def copy(src, dst):
if os.path.islink(src):
if os.path.lexists(dst):
os.unlink(dst)
linkto = os.readlink(src)
os.symlink(linkto, dst)
else:
shutil.copy(src, dst)
if __name__ == '__main__':
os.symlink('c', 'b')
os.symlink('b', 'a')
copy('a', 'b')
with open('c', 'w') as f:
f.write('a')
with open('d', 'w'):
pass
copy('c', 'd')
copy('a', 'c')
在Ubuntu 18.10,Python 3.6.7中进行了测试。