ファイルsrc
を宛先dst
にコピーしたいのですが、src
がシンボリックリンクである場合は、ファイルの内容をコピーするのではなく、リンクを保持してください。コピーが実行された後、os.readlink
はsrc
とdst
の両方に対して同じものを返す必要があります。
モジュールshutil
にはcopyfile
、copy
、copy2
などのいくつかの関数がありますが、これらはすべてコピーされますcontents ofファイルであり、リンクは保持されません。 shutil.move
は、元のファイルを削除するという事実を除いて、正しい動作をします。
Pythonに、シンボリックリンクを保持しながらファイルコピーを実行する組み込みの方法はありますか?
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が参照するファイルのコピーになります。
ただし、これには1つの問題があります。既存のファイルまたはシンボリックリンクを上書きしようとすると、次のように失敗します。
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。
ただやる
def copy(src, dst):
if os.path.islink(src):
linkto = os.readlink(src)
os.symlink(linkto, dst)
else:
shutil.copy(src,dst)
shutil.copytree は似たようなことをしますが、senderleが指摘したように、単一のファイルではなく、ディレクトリのみをコピーするのは慎重です。