Pythonでファイルをコピーするにはどうすればよいですか?


2478

Pythonでファイルをコピーするにはどうすればよいですか?

下に何も見つかりませんでしたos


117
cpはシステムコールではないため、osモジュールに属していないようです。これはシェルコマンドなので、shutilモジュールに入れられます。
waldol1 2013年

回答:


3011

shutilあなたが使用できる多くの方法があります。その1つは次のとおりです。

from shutil import copyfile
copyfile(src, dst)
  • srcという名前のファイルの内容をdstという名前のファイルにコピーします。
  • 宛先の場所は書き込み可能でなければなりません。それ以外の場合は、IOError例外が発生します。
  • dstがすでに存在する場合は、置き換えられます。
  • キャラクターデバイスやブロックデバイス、パイプなどの特殊ファイルは、この関数ではコピーできません。
  • コピーSRCDSTとして指定されたパス名で文字列が

os.path操作を使用する場合copyは、ではなくを使用してくださいcopyfilecopyfile文字列のみを受け入れます


147
copyとcopyfileの違いは何ですか?
Matt

387
copy(src、dst)では、dstをディレクトリにすることができます。
オーウェン

41
プラットフォームによっては、すべてのメタデータがコピーされるわけではないことに注意してください。
ケビンホーン

12
これはアトミック操作ではないことに注意してください。スレッド化されたアプリケーションでの使用には注意してください。
ウォーターバイト2018年

4
のような省略形~は処理できませんが、相対パスは処理できます
zwep

1253
┌──────────────────┬────────┬───────────┬───────┬────────────────┐
│     Function     │ Copies │   Copies  │Can use│   Destination  │
│                  │metadata│permissions│buffer │may be directory│
├──────────────────┼────────┼───────────┼───────┼────────────────┤
│shutil.copy       │   No   │    Yes    │   No  │      Yes       │
│shutil.copyfile   │   No   │     No    │   No  │       No       │
│shutil.copy2      │  Yes   │    Yes    │   No  │      Yes       │
│shutil.copyfileobj│   No   │     No    │  Yes  │       No       │
└──────────────────┴────────┴───────────┴───────┴────────────────┘

732

copy2(src,dst)多くの場合、次のcopyfile(src,dst)理由よりも便利です。

  • それが可能dstであることがディレクトリ(代わりの完全なターゲットファイル名)、その場合、ベース名src新しいファイルを作成するために使用されます。
  • 元の変更とアクセス情報(mtimeとatime)をファイルメタデータに保存します(ただし、これにはわずかなオーバーヘッドが伴います)。

以下に短い例を示します。

import shutil
shutil.copy2('/src/dir/file.ext', '/dst/dir/newname.ext') # complete target filename given
shutil.copy2('/src/file.ext', '/dst/dir') # target filename is /dst/dir/file.ext

19
100万ファイルから100kファイルをランダムにコピーしようとしています。copyfileかなり速くよりcopy2
ビジェイ

4
私はそれを想定して修正していますshutil.copy2('/dir/file.ext', '/new/dir/')「DIR」と呼ばれる新しいファイルにコピーするか、その名前のディレクトリにファイルを配置するかどうかの上にあいまいさを削除します(ターゲットパスの後にスラッシュ)?
Zak

1
@Vijayこのオーバーヘッドはメタデータのコピーによるものだと思います。
Jonathan H

@Zak /new/dir既存のディレクトリである場合、あいまいさはありません。@ MatthewAlpertのコメントを参照してください。
Jonathan H

@Zak正解です。末尾にスラッシュを追加すると、あいまいさがなくなります。場合は/new/dir/存在しない、PythonがスローされますIsADirectoryErrorし、それ以外の場合はコピーしたファイルを/new/dir/元の名前の下に。
martonbognar

125

shutilパッケージのコピー機能の1つを使用できます。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
機能はサポートを支持します他のコピーを受け入れます
                      権限ディレクトリdest。ファイルobjメタデータ  
―――――――――――――――――――――――――――――――――――――――――――――――――― ――――――――――――――――――――――――――――
shutil.copy               ✔✔☐☐
 shutil.copy2              ✔✔☐✔
 shutil.copyfile           ☐☐☐☐
 shutil.copyfileobj        ☐☐✔☐
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

例:

import shutil
shutil.copy('/etc/hostname', '/var/tmp/testhostname')

10
好奇心旺盛ですが、どのようにしてそのテーブルを生成しましたか?
光錬金術師、

16
@lightalchemist vimをスクラッチパッドとして使用し、使用したUnicodeシンボルをウィキペディアのテーブルからコピーして、最終的な仕上げのためにその結果をstackoverflowエディターにコピーしました。
maxschlepzig 2018

3
これは2年前の他の回答とどう違うのですか? stackoverflow.com/a/30359308/674039
wim

1
@wim、私の回答を、私が私の回答を投稿したときに最新であった、リンクした回答の2017バージョンと比較する必要があります。主な違い:私の答えはより良い/より説明的な列ヘッダーを使用し、テーブルのレイアウトは邪魔にならず、ドキュメントへの直接リンクが含まれ、列を追加しました(つまり、「ファイルobjを受け入れる」)。
maxschlepzig

4
OK。YMMVですが、見た目の変更やそのようなマイナーな改善は、回答を複製するよりも、既存の回答を編集する方がよいと思います。
WIM

104

Pythonでは、次を使用してファイルをコピーできます。


import os
import shutil
import subprocess

1)shutilモジュールを使用してファイルをコピーする

shutil.copyfile 署名

shutil.copyfile(src_file, dest_file, *, follow_symlinks=True)

# example    
shutil.copyfile('source.txt', 'destination.txt')

shutil.copy 署名

shutil.copy(src_file, dest_file, *, follow_symlinks=True)

# example
shutil.copy('source.txt', 'destination.txt')

shutil.copy2 署名

shutil.copy2(src_file, dest_file, *, follow_symlinks=True)

# example
shutil.copy2('source.txt', 'destination.txt')  

shutil.copyfileobj 署名

shutil.copyfileobj(src_file_object, dest_file_object[, length])

# example
file_src = 'source.txt'  
f_src = open(file_src, 'rb')

file_dest = 'destination.txt'  
f_dest = open(file_dest, 'wb')

shutil.copyfileobj(f_src, f_dest)  

2)osモジュールを使用してファイルをコピーする

os.popen 署名

os.popen(cmd[, mode[, bufsize]])

# example
# In Unix/Linux
os.popen('cp source.txt destination.txt') 

# In Windows
os.popen('copy source.txt destination.txt')

os.system 署名

os.system(command)


# In Linux/Unix
os.system('cp source.txt destination.txt')  

# In Windows
os.system('copy source.txt destination.txt')

3)subprocessモジュールを使用してファイルをコピーする

subprocess.call 署名

subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)

# example (WARNING: setting `shell=True` might be a security-risk)
# In Linux/Unix
status = subprocess.call('cp source.txt destination.txt', shell=True) 

# In Windows
status = subprocess.call('copy source.txt destination.txt', shell=True)

subprocess.check_output 署名

subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)

# example (WARNING: setting `shell=True` might be a security-risk)
# In Linux/Unix
status = subprocess.check_output('cp source.txt destination.txt', shell=True)

# In Windows
status = subprocess.check_output('copy source.txt destination.txt', shell=True)


9
単一文字列コマンドの使用はコーディングスタイル(柔軟性、信頼性、セキュリティ)が悪いため['copy', sourcefile, destfile]、特にパラメーターがユーザー入力からのものである場合は、可能な限り構文を使用してください。
Marcel Waldvogel、

8
なぜ、shutilのコピー機能にそれほど多くの悪い代替案を挙げているのですか?
maxschlepzig

6
shutilは組み込みで、移植性のない代替物を提供する必要はありません。答えはシステムに依存するソリューションを削除することで実際に改善される可能性があり、その削除後、この回答は既存の回答のコピー/ドキュメントのコピーになります。
ジャン=フランソワ・ファーブル

3
os.popenしばらくは非推奨です。そしてcheck_outputステータスが、(の場合には空である出力戻らないcopy/cp
ジーン・フランソワ・ファーブル

2
shutilは実際にはファイルをコピーしません。ドキュメントの一番上に大きな太った警告があります。「これは、ファイルの所有者とグループ、およびACLが失われることを意味します。MacOSでは、リソースフォークと他のメタデータは使用されません。これは、リソースが失われ、ファイルタイプと作成者コードが正しくなくなることを意味します。Windowsではファイルの所有者、ACL、代替データストリームはコピーされません。」
gman

96

以下の例に示すように、ファイルのコピーは比較的簡単な操作ですが、代わりにshutil stdlibモジュールを使用する必要があります。

def copyfileobj_example(source, dest, buffer_size=1024*1024):
    """      
    Copy a file from source to dest. source and dest
    must be file-like objects, i.e. any object with a read or
    write method, like for example StringIO.
    """
    while True:
        copy_buffer = source.read(buffer_size)
        if not copy_buffer:
            break
        dest.write(copy_buffer)

ファイル名でコピーしたい場合は、次のようにします。

def copyfile_example(source, dest):
    # Beware, this example does not handle any edge cases!
    with open(source, 'rb') as src, open(dest, 'wb') as dst:
        copyfileobj_example(src, dst)

25
私はしばらく前に、モジュールがshutil(単数形)とないshutils(複数)と呼ばれていることに気づき、そして実際にそれがあるのPython 2.3で。それでも、ここでは例としてこの関数を残します。
pi。

4
ファイルの内容のコピーは簡単な操作です。ファイルとそのメタデータをコピーするのは簡単ではありません。クロスプラットフォームになりたい場合はなおさらです。
LaC、2012年

3
本当です。shutil docsを見ると、copyfile関数もメタデータをコピーしません。
pi。

3
はい、なぜのソースをコピーしないのかわかりませんshutil.copyfileobj。また、try, finally例外後のファイルのクローズを処理する必要はありません。ただし、関数はファイルを開いたり閉じたりする必要はありません。これは、shutil.copyfilewrapsのようなラッパー関数に入れるべきshutil.copyfileobjです。
ErlVolton 2014年

2
上記のコードはdest書き込み可能に指定する必要があります:open(dest, 'wb')
user1016274

69

shutilモジュールを使用します

copyfile(src, dst)

srcという名前のファイルの内容をdstという名前のファイルにコピーします。宛先の場所は書き込み可能でなければなりません。それ以外の場合は、IOError例外が発生します。dstがすでに存在する場合は、置き換えられます。キャラクターデバイスやブロックデバイス、パイプなどの特殊ファイルは、この関数ではコピーできません。srcおよびdstは、文字列として指定されたパス名です。

見てみましょうのfilesys標準のPythonモジュールで使用可能なすべてのファイルとディレクトリの取り扱い機能のために。


shutilは実際にはファイルをコピーしません。ドキュメントの一番上に大きな太った警告があります。「これは、ファイルの所有者とグループ、およびACLが失われることを意味します。MacOSでは、リソースフォークと他のメタデータは使用されません。これは、リソースが失われ、ファイルタイプと作成者コードが正しくなくなることを意味します。Windowsではファイルの所有者、ACL、代替データストリームはコピーされません。」
gman

47

ディレクトリとファイルのコピー例-Tim GoldenのPythonスタッフから:

http://timgolden.me.uk/python/win32_how_do_i/copy-a-file.html

import os
import shutil
import tempfile

filename1 = tempfile.mktemp (".txt")
open (filename1, "w").close ()
filename2 = filename1 + ".copy"
print filename1, "=>", filename2

shutil.copy (filename1, filename2)

if os.path.isfile (filename2): print "Success"

dirname1 = tempfile.mktemp (".dir")
os.mkdir (dirname1)
dirname2 = dirname1 + ".copy"
print dirname1, "=>", dirname2

shutil.copytree (dirname1, dirname2)

if os.path.isdir (dirname2): print "Success"

24

まず、参考のために、shutilメソッドの完全なチートシートを作成しました。

shutil_methods =
{'copy':['shutil.copyfileobj',
          'shutil.copyfile',
          'shutil.copymode',
          'shutil.copystat',
          'shutil.copy',
          'shutil.copy2',
          'shutil.copytree',],
 'move':['shutil.rmtree',
         'shutil.move',],
 'exception': ['exception shutil.SameFileError',
                 'exception shutil.Error'],
 'others':['shutil.disk_usage',
             'shutil.chown',
             'shutil.which',
             'shutil.ignore_patterns',]
}

次に、例としてコピーの方法を説明します。

  1. shutil.copyfileobj(fsrc, fdst[, length]) 開いたオブジェクトを操作する
In [3]: src = '~/Documents/Head+First+SQL.pdf'
In [4]: dst = '~/desktop'
In [5]: shutil.copyfileobj(src, dst)
AttributeError: 'str' object has no attribute 'read'
#copy the file object
In [7]: with open(src, 'rb') as f1,open(os.path.join(dst,'test.pdf'), 'wb') as f2:
    ...:      shutil.copyfileobj(f1, f2)
In [8]: os.stat(os.path.join(dst,'test.pdf'))
Out[8]: os.stat_result(st_mode=33188, st_ino=8598319475, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067347, st_mtime=1516067335, st_ctime=1516067345)
  1. shutil.copyfile(src, dst, *, follow_symlinks=True) コピーして名前を変更
In [9]: shutil.copyfile(src, dst)
IsADirectoryError: [Errno 21] Is a directory: ~/desktop'
#so dst should be a filename instead of a directory name
  1. shutil.copy() メタデータを事前に提示せずにコピーする
In [10]: shutil.copy(src, dst)
Out[10]: ~/desktop/Head+First+SQL.pdf'
#check their metadata
In [25]: os.stat(src)
Out[25]: os.stat_result(st_mode=33188, st_ino=597749, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516066425, st_mtime=1493698739, st_ctime=1514871215)
In [26]: os.stat(os.path.join(dst, 'Head+First+SQL.pdf'))
Out[26]: os.stat_result(st_mode=33188, st_ino=8598313736, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516066427, st_mtime=1516066425, st_ctime=1516066425)
# st_atime,st_mtime,st_ctime changed
  1. shutil.copy2() メタデータを事前にコピーしてコピー
In [30]: shutil.copy2(src, dst)
Out[30]: ~/desktop/Head+First+SQL.pdf'
In [31]: os.stat(src)
Out[31]: os.stat_result(st_mode=33188, st_ino=597749, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067055, st_mtime=1493698739, st_ctime=1514871215)
In [32]: os.stat(os.path.join(dst, 'Head+First+SQL.pdf'))
Out[32]: os.stat_result(st_mode=33188, st_ino=8598313736, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=13507926, st_atime=1516067063, st_mtime=1493698739, st_ctime=1516067055)
# Preseved st_mtime
  1. shutil.copytree()

srcをルートとするディレクトリツリー全体を再帰的にコピーし、宛先ディレクトリを返します


1
shutilは実際にはファイルをコピーしません。ドキュメントの一番上に大きな太った警告があります。「これは、ファイルの所有者とグループ、およびACLが失われることを意味します。MacOSでは、リソースフォークと他のメタデータは使用されません。これは、リソースが失われ、ファイルタイプと作成者コードが正しくなくなることを意味します。Windowsではファイルの所有者、ACL、代替データストリームはコピーされません。」
gman

19

小さなファイルでpython組み込みのみを使用する場合は、次のワンライナーを使用できます。

with open(source, 'rb') as src, open(dest, 'wb') as dst: dst.write(src.read())

@maxschlepzigが以下のコメントで言及されているように、これはファイルが大きすぎるアプリケーションやメモリが重要な場合の最適な方法ではないため、Swatiの回答をお勧めします。


3
これにより、ソースファイル全体がメモリに読み込まれてから、書き戻されます。したがって、これは、最小のファイルコピー操作を除くすべてのメモリを不必要に浪費します。
maxschlepzig 2017年

1
本当?私が考える.read().write()(少なくとも、CPythonのための)デフォルトではバッファリングされています。
サウンドストライプ、

@soundstripe、もちろんこれは本当です。によって返されたファイルオブジェクトopen()がデフォルトでバッファIOを実行するという事実は、次のようにread()指定されているため、ここでは役に立ちません。「nが負であるか省略されている場合は、EOFまで読み取ります。」つまり、read()は完全なファイルコンテンツを文字列として返します。
maxschlepzig

@maxschlepzig私はあなたのポイントを理解し、私はそれを知らなかったと認めます。私がこの回答を提供した理由は、誰かが組み込みモジュールのみを使用して単純なファイルコピーを行い、そのためのモジュールをインポートする必要がない場合でした。もちろん、このオプションが必要な場合、メモリの最適化は問題になりません。とにかくそれを片付けてくれてありがとう。私はそれに応じて答えを更新しました。
yellow01

14

あなたは使うことができます os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')

または私がやったように、

os.system('cp '+ rawfile + ' rawdata.dat')

rawfileプログラム内で生成した名前はどこですか。

これはLinuxのみのソリューションです


10
これは移植性がなく、shutilを使用できるだけなので不要です。
Corey Goldberg 2017年

4
shutilが利用できない場合でも- subprocess.run() (なしshell=True!)がのより良い代替手段os.system()です。
maxschlepzig 2017

1
shutilの方が移植性が高い
Hiadore

1
subprocess.run()@maxschlepzigによって提案されているように、外部プログラムを呼び出すときは大きな前進です。ただし、柔軟性とセキュリティのために['cp', rawfile, 'rawdata.dat']、コマンドラインを渡す形式を使用します。(ただし、コピーにshutilは、外部プログラムを呼び出すよりも友人をお勧めします。)
Marcel Waldvogel

2
スペースを含むファイル名でそれを試してください。
ジャン=フランソワ・ファーブル

11

大きなファイルの場合、ファイルを1行ずつ読み取り、各行を配列に読み込みました。次に、配列が特定のサイズに達したら、新しいファイルに追加します。

for line in open("file.txt", "r"):
    list.append(line)
    if len(list) == 1000000: 
        output.writelines(list)
        del list[:]

2
ライターはバッファリングを処理する必要があるため、これは少し冗長に見えます。for l in open('file.txt','r'): output.write(l)機能するはずです。必要に応じて出力ストリームバッファをセットアップするだけです。または、一度に書き込みたいバイト数がoutput.write(read(n)); output.flush()どこnであるかを試行してループすることにより、バイト単位で移動できます。これらはどちらもボーナスであるかどうかをチェックする条件がありません。
2015年

1
はい、しかし、これは行の一部ではなく行全体をコピーするため、理解しやすいかもしれないと思いました(各行のバイト数がわからない場合)。
ytpillai 2015年

とても本当です。効率を上げるためのコーディングとコーディングは大きく異なります。
所有

1
ソースを見る-writelinesはwrite、hg.python.org/cpython/file/c6880edaf6f3/Modules/_io/bytesio.cを呼び出します。また、ファイルストリームは既に開いているので、書き込みのたびに再度開く必要はありません。
所有

2
これはひどいです。正当な理由もなく不要な作業を行います。任意のファイルに対しては機能しません。Windowsなどのシステムで入力に異常な行末がある場合、コピーはバイト単位ではありません。なぜこれはコピー関数の呼び出しよりも理解しやすいと思いますshutilか?を無視shutilする場合でも、単純なブロックの読み取り/書き込みループ(バッファリングされていないIOを使用)は単純であり、効率的であり、これよりもはるかに理にかなっているため、教えることと理解することは確かに簡単です。
maxschlepzig

11
from subprocess import call
call("cp -p <file> <file>", shell=True)

10
これはプラットフォームに依存するので、使用しません。
Kevin Meier

5
このようなa callは安全ではありません。それについては、サブプロセスのドキュメントを参照してください。
buhtz 2017

2
これは移植性がなく、shutilを使用できるだけなので不要です。
Corey Goldberg 2017年

2
では、なぜPythonなのでしょうか。
Baris Demiray 2017

開始前にオペレーティングシステムを検出する可能性があります(DOSとUnixのどちらでも、2つが最もよく使用されているため)
MilkyWay90

8

以下のようPythonの3.5あなたは小さなファイル(テキストファイル、JPEGファイル小さなIE)のために、以下の操作を行うことができます。

from pathlib import Path

source = Path('../path/to/my/file.txt')
destination = Path('../path/where/i/want/to/store/it.txt')
destination.write_bytes(source.read_bytes())

write_bytes 宛先の場所にあったものを上書きします


2
そして、誰かが大きなファイルで(偶然または故意に)コードを使用します…の関数を使用するとshutil、すべての特殊なケースに対応し、安心できます。
Marcel Waldvogel

4
少なくとも、同じソリューションを何度も繰り返すことはありません。
ジャン=フランソワ・ファーブル

6
open(destination, 'wb').write(open(source, 'rb').read())

ソースファイルを読み取りモードで開き、書き込みモードで宛先ファイルに書き込みます。


1
アイデアは素晴らしく、コードは美しいですが、適切なcopy()関数は、属性(+ xビット)のコピーや、たとえば、ディスクがいっぱいの状態が見つかった場合にすでにコピーされたバイトを削除するなど、さらに多くのことができます。 。
ラウル・サリナス- Monteagudo

1
たとえ一文であっても、すべての回答には説明が必要です。説明がないのは悪い先例であり、プログラムの理解には役立ちません。完全なPython noobがやって来て、これを見て、それを使用したいと思ったが、理解できないために使用できなかった場合はどうなりますか?あなたはあなたの答えですべてに役立つことを望んでいます。
connectyourcharger

1
.close()それらすべてのopen(...)s が欠けていませんか?
ラッキードナルド

.close()の必要はありません。ファイルポインタオブジェクトを(srcファイルでも宛先ファイルでも)どこにも格納しないためです。
S471

1
yellow01の回答と同じ次善のメモリ浪費アプローチ。
maxschlepzig

-3

Pythonには、オペレーティングシステムシェルユーティリティを使用してファイルを簡単にコピーするための組み込み関数が用意されています。

次のコマンドを使用してファイルをコピーします

shutil.copy(src,dst)

次のコマンドを使用して、メタデータ情報を含むファイルをコピーします

shutil.copystat(src,dst)

copy次に実行copystatして、ファイルのメタデータを保持する必要があります。Python 3.3以降でcopystatは、拡張属性もコピーされます。
ingyhere
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.