Como copiar um arquivo em Python?

2478

Como copiar um arquivo em Python?

Não consegui encontrar nada embaixo os.

Matt
fonte
117
Parece que cp não é uma chamada do sistema e, portanto, não pertence ao módulo os. É um comando shell, por isso é colocado no módulo shutil.
waldol1

Respostas:

3011

shutiltem muitos métodos que você pode usar. Um dos quais é:

from shutil import copyfile
copyfile(src, dst)
  • Copie o conteúdo do arquivo chamado src para um arquivo chamado dst .
  • O local de destino deve ser gravável; caso contrário, uma exceção IOError será gerada.
  • Se o dst já existir, será substituído.
  • Arquivos especiais como dispositivos de caractere ou bloco e tubulações não podem ser copiados com esta função.
  • Com copy , src e dst são nomes de caminhos dados como strings .

Se você usar os.pathoperações, use em copyvez de copyfile. copyfilevai aceitar apenas cordas .

Swati
fonte
147
Qual é a diferença entre copy e copyfile?
Matt
387
na cópia (src, dst), o dst pode ser um diretório.
Owen
41
Observe que nem todos os metadados serão copiados, dependendo da sua plataforma.
21119 Kevin Horn
12
Observe que não é uma operação atômica. Tome cuidado ao usá-lo em um aplicativo encadeado.
Waterbyte 22/10/19
4
Note que ele não pode lidar com abreviaturas como ~, mas pode lidar com caminhos relativos
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       │
└──────────────────┴────────┴───────────┴───────┴────────────────┘
jezrael
fonte
732

copy2(src,dst)geralmente é mais útil do que copyfile(src,dst)porque:

  • permite dstser um diretório (em vez do nome completo do nome do arquivo); nesse caso, o nome da base srcé usado para criar o novo arquivo;
  • ele preserva as informações originais de modificação e acesso (mtime e atime) nos metadados do arquivo (no entanto, isso vem com uma ligeira sobrecarga).

Aqui está um pequeno exemplo:

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
desmontado
fonte
19
Estou tentando copiar aleatoriamente 100k arquivos de 1 milhão de arquivos. copyfileé consideravelmente mais rápido do quecopy2
Vijay
4
estou correto ao assumir que shutil.copy2('/dir/file.ext', '/new/dir/')(com barra após o caminho de destino) removerá a ambiguidade sobre copiar para um novo arquivo chamado "dir" ou colocar o arquivo em um diretório com esse nome?
Zak
1
@ Vijay Acredito que essa sobrecarga se deva à cópia dos metadados.
Jonathan H
@ Zak Não há ambiguidade se /new/dirhouver um diretório existente, consulte o comentário de @ MatthewAlpert.
Jonathan H
@ Zak Você está correto, adicionar uma barra ao final remove a ambiguidade. Se /new/dir/não existir, o Python lançará um IsADirectoryError, caso contrário, ele copiará o arquivo para /new/dir/o nome original.
Martonbognar
125

Você pode usar uma das funções de cópia do shutilpacote:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
A função preserva suportes aceita cópias de outros
                      diretório de permissões dest. metadados do objeto de arquivo  
― ― ― ― ― ― ――――――――――――――――――――――――
shutil.copy               ✔ ☐
 shutil.copy2              ✔ ✔ ✔
 shutil.copyfile           ☐ ☐ ☐
 shutil.copyfileobj        ☐ ☐ ✔
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Exemplo:

import shutil
shutil.copy('/etc/hostname', '/var/tmp/testhostname')
maxschlepzig
fonte
10
Apenas curioso, como você gerou essa tabela?
Lightalchemist
16
@lightalchemist Acabei de usar o vim como raspadinha, copiei os símbolos unicode usados ​​de uma tabela da wikipedia e copiei o resultado no editor stackoverflow para o polimento final.
Maxschlepzig 02/12
3
Como isso difere de outras respostas 2 anos antes? stackoverflow.com/a/30359308/674039
wim
1
@ wim, você precisa comparar minha resposta com a versão de 2017 da resposta que você vinculou, que estava atual quando eu publiquei minha resposta. Principais diferenças: minha resposta usa cabeçalhos de colunas melhores / mais descritivos, o layout da tabela não é perturbador, inclui links diretos para a documentação e adicionei uma coluna (por exemplo, 'aceita obj. De arquivo').
maxschlepzig
4
ESTÁ BEM. YMMV, mas acho que mudanças cosméticas e pequenas melhorias como essas são melhor feitas como edições nas respostas existentes, em vez de duplicação de respostas.
Wim
104

No Python, você pode copiar os arquivos usando


import os
import shutil
import subprocess

1) Copiando arquivos usando o shutilmódulo

shutil.copyfile assinatura

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

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

shutil.copy assinatura

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

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

shutil.copy2 assinatura

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

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

shutil.copyfileobj assinatura

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) Copiando arquivos usando o osmódulo

os.popen assinatura

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 assinatura

os.system(command)


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

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

3) Copiando arquivos usando o subprocessmódulo

subprocess.call assinatura

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 assinatura

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)

kmario23
fonte
9
O uso de comandos de cadeia única é um estilo de codificação ruim (flexibilidade, confiabilidade e segurança); em vez disso, use a ['copy', sourcefile, destfile]sintaxe sempre que possível, especialmente se os parâmetros forem da entrada do usuário.
Marcel Waldvogel
8
Por que você lista tantas alternativas ruins para as funções de cópia fechada?
maxschlepzig
6
shutil é embutido, não há necessidade de fornecer alternativas não portáteis. A resposta pode ser melhorada removendo as soluções dependentes do sistema e, após essa remoção, essa resposta é apenas uma cópia das respostas existentes / uma cópia da documentação.
Jean-François Fabre
3
os.popenestá obsoleto por um tempo agora. e check_outputnão retorna o status, mas a saída (que está vazia no caso de copy/cp)
Jean-François Fabre
2
shutil na verdade não copia arquivos. Há um grande aviso bem no topo da documentação . "isso significa que o proprietário e o grupo do arquivo são perdidos e também as ACLs. No Mac OS, a bifurcação de recursos e outros metadados não são usados. Isso significa que os recursos serão perdidos e os códigos de criador e tipo de arquivo não estarão corretos. No Windows, proprietários de arquivos, ACLs e fluxos de dados alternativos não são copiados. "
gman
96

Copiar um arquivo é uma operação relativamente direta, como mostra os exemplos abaixo, mas você deve usar o módulo shutil stdlib para isso.

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)

Se você deseja copiar por nome de arquivo, você pode fazer algo assim:

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)
pi.
fonte
25
Percebi há algum tempo que o módulo é chamado shutil (singular) e não shutils (plural), e de fato está no Python 2.3. No entanto, deixo essa função aqui como um exemplo.
pi.
4
Copiar o conteúdo de um arquivo é uma operação simples. Copiar o arquivo com seus metadados é tudo menos direto, ainda mais se você quiser ser multiplataforma.
LaC 16/01/12
3
Verdade. Observando os documentos do shutil, a função copyfile também não copiará metadados.
pi.
3
Sim, não sei por que você não copiou apenas a fonte de shutil.copyfileobj. Além disso, você não precisa try, finallylidar com o fechamento dos arquivos após exceções. Eu diria, no entanto, que sua função não deve ser responsável por abrir e fechar os arquivos. Isso deve incluir uma função de invólucro, como os shutil.copyfileenvoltórios shutil.copyfileobj.
ErlVolton
2
O código acima deve especificar destpara ser gravável:open(dest, 'wb')
user1016274
69

Use o módulo shutil .

copyfile(src, dst)

Copie o conteúdo do arquivo chamado src para um arquivo chamado dst. O local de destino deve ser gravável; caso contrário, uma exceção IOError será gerada. Se o dst já existir, será substituído. Arquivos especiais como dispositivos de caractere ou bloco e tubulações não podem ser copiados com esta função. src e dst são nomes de caminho dados como strings.

Dê uma olhada no filesys para todas as funções de manipulação de arquivos e diretórios disponíveis nos módulos padrão do Python.

Airsource Ltd
fonte
shutil na verdade não copia arquivos. Há um grande aviso bem no topo da documentação . "isso significa que o proprietário e o grupo do arquivo são perdidos e também as ACLs. No Mac OS, a bifurcação de recursos e outros metadados não são usados. Isso significa que os recursos serão perdidos e os códigos de criador e tipo de arquivo não estarão corretos. No Windows, proprietários de arquivos, ACLs e fluxos de dados alternativos não são copiados. "
gman
47

Exemplo de cópia de diretório e arquivo - do Python de Tim Golden:

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"
Noam Manos
fonte
24

Em primeiro lugar, fiz uma cheatsheet exaustiva dos métodos shutil para sua referência.

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',]
}

Em segundo lugar, explique os métodos de cópia nos exemplos:

  1. shutil.copyfileobj(fsrc, fdst[, length]) manipular objetos abertos
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) Copie e renomeie
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() Copiar sem preservar os metadados
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() Copiar preservando os metadados
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()

Copie recursivamente uma árvore de diretórios inteira enraizada no src, retornando o diretório de destino

Cálculo
fonte
1
shutil na verdade não copia arquivos. Há um grande aviso bem no topo da documentação . "isso significa que o proprietário e o grupo do arquivo são perdidos e também as ACLs. No Mac OS, a bifurcação de recursos e outros metadados não são usados. Isso significa que os recursos serão perdidos e os códigos de criador e tipo de arquivo não estarão corretos. No Windows, proprietários de arquivos, ACLs e fluxos de dados alternativos não são copiados. "
gman
19

Para arquivos pequenos e usando apenas built-ins python, você pode usar o seguinte recurso:

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

Como o @maxschlepzig mencionado nos comentários abaixo, esta não é a maneira ideal para aplicativos em que o arquivo é muito grande ou quando a memória é crítica, portanto, a resposta de Swati deve ser a preferida.

yellow01
fonte
3
Isso lê o arquivo de origem completo na memória antes de gravá-lo novamente. Portanto, isso desperdiça desnecessariamente memória para todas, exceto as menores operações de cópia de arquivo.
maxschlepzig
1
Isso é verdade? Penso .read()e .write()são armazenados em buffer por padrão (pelo menos para CPython).
soundstripe
@ soundstripe, é claro que isso é verdade. O fato de o objeto de arquivo retornado por open()IO em buffer, por padrão, não ajuda aqui, porque read()é especificado como: 'Se n for negativo ou omitido, leia até EOF'. Isso significa que read()retorna o conteúdo completo do arquivo como uma sequência.
Maxschlepzig
@maxschlepzig Entendi seu ponto de vista e admito que não estava ciente disso. O motivo pelo qual forneci essa resposta foi no caso de alguém querer fazer uma cópia simples de arquivo usando apenas os recursos internos, sem precisar importar um módulo para ela. Obviamente, a otimização de memória não deve ser uma preocupação se você deseja esta opção. De qualquer forma, obrigado por esclarecer isso. Eu atualizei a resposta de acordo.
yellow01
14

Você poderia usar os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')

ou como eu fiz isso,

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

Onde rawfileestá o nome que eu havia gerado dentro do programa.

Esta é uma solução apenas para Linux

marca
fonte
10
isso não é portátil e desnecessário, pois você pode usar o shutil.
Corey Goldberg
4
Mesmo quando shutilnão está disponível - subprocess.run() (sem shell=True!) É a melhor alternativa para os.system().
maxschlepzig
1
shutil é mais portátil
Hiadore
1
subprocess.run()como sugerido por @maxschlepzig, é um grande passo em frente ao chamar programas externos. Para flexibilidade e segurança, no entanto, use a ['cp', rawfile, 'rawdata.dat']forma de passar a linha de comando. (No entanto, para cópia, shutile os amigos são mais recomendadas que chamar um programa externo.)
Marcel Waldvogel
2
tente isso com nomes de arquivos com espaços.
Jean-François Fabre
11

Para arquivos grandes, o que eu fiz foi ler o arquivo linha por linha e ler cada linha em uma matriz. Depois que o array atingir um determinado tamanho, anexe-o a um novo arquivo.

for line in open("file.txt", "r"):
    list.append(line)
    if len(list) == 1000000: 
        output.writelines(list)
        del list[:]
ytpillai
fonte
2
isso parece um pouco redundante, pois o gravador deve lidar com o buffer. for l in open('file.txt','r'): output.write(l)deve trabalhar encontrar; basta configurar o buffer do fluxo de saída de acordo com suas necessidades. ou você pode acessar os bytes repetindo uma tentativa com output.write(read(n)); output.flush()onde nestá o número de bytes que você deseja escrever por vez. ambos também não têm condições de verificar qual é um bônus.
detém
1
Sim, mas achei que talvez isso fosse mais fácil de entender porque copia linhas inteiras em vez de partes delas (caso não saibamos quantos bytes cada linha possui).
ytpillai
Muito verdadeiro. Codificação para ensino e codificação para eficiência são muito diferentes.
detém
1
olhando para a fonte - as chamadas writelines write, hg.python.org/cpython/file/c6880edaf6f3/Modules/_io/bytesio.c . Além disso, o fluxo de arquivos já está aberto, portanto, a gravação não precisaria reabri-lo toda vez.
possui
2
Isso é horrível. Faz um trabalho desnecessário sem um bom motivo. Não funciona para arquivos arbitrários. A cópia não é idêntica a byte se a entrada tiver terminações de linhas incomuns em sistemas como o Windows. Por que você acha que isso pode ser mais fácil de entender do que uma chamada para uma função de cópia shutil? Mesmo quando ignorado shutil, um simples loop de leitura / gravação de bloco (usando IO sem buffer) é direto, seria eficiente e faria muito mais sentido do que isso e, portanto, é certamente mais fácil de ensinar e entender.
maxschlepzig
11
from subprocess import call
call("cp -p <file> <file>", shell=True)
mergulho profundo
fonte
10
Isso depende da plataforma, então eu não usaria.
Kevin Meier
5
Tal callé inseguro. Consulte os subprocessos sobre isso.
buhtz
2
isso não é portátil e desnecessário, pois você pode usar o shutil.
Corey Goldberg
2
Hmm, por que Python, então?
Baris Demiray
Talvez detectar o sistema operacional antes de iniciar (se é DOS ou Unix, porque aqueles são os dois mais utilizados)
MilkyWay90
8

No Python 3.5, você pode fazer o seguinte para arquivos pequenos (por exemplo: arquivos de texto, jpegs pequenos):

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 substituirá o que estava no local de destino

Marc
fonte
2
E então alguém usa o código (acidental ou intencionalmente) em um arquivo grande ... O uso das funções de shutillida com todos os casos especiais para você e oferece tranqüilidade.
Marcel Waldvogel
4
pelo menos, não repete as mesmas soluções repetidamente.
Jean-François Fabre
6
open(destination, 'wb').write(open(source, 'rb').read())

Abra o arquivo de origem no modo de leitura e grave no arquivo de destino no modo de gravação.

S471
fonte
1
A idéia é boa e o código é bonito, mas uma função copy () adequada pode fazer mais coisas, como copiar atributos (+ x bit) ou, por exemplo, excluir os bytes já copiados, caso seja encontrada uma condição de disco cheio .
Raúl Salinas-Monteagudo
1
Todas as respostas precisam de explicação, mesmo que seja uma frase. Nenhuma explicação define um precedente ruim e não é útil para entender o programa. E se um noob completo do Python aparecesse e visse isso, quisesse usá-lo, mas não pudesse porque não o entende? Você quer ser útil para todos em suas respostas.
connectyourcharger
1
Isso não está faltando .close()em todos esses open(...)s?
luckydonald
Não há necessidade de .close (), pois NÃO ESTÃO ARMAZENANDO o objeto ponteiro de arquivo em nenhum lugar (nem no arquivo src nem no arquivo de destino).
S471 23/04/19
1
Mesma abordagem de desperdício de memória abaixo do ideal que a resposta de yellow01 .
maxschlepzig
-3

O Python fornece funções integradas para copiar facilmente arquivos usando os utilitários de shell do sistema operacional.

O comando a seguir é usado para copiar arquivo

shutil.copy(src,dst)

O comando a seguir é usado para Copiar Arquivo com Informações MetaData

shutil.copystat(src,dst)
Savai Maheshwari
fonte
Você deve executar copyentão copystatpara preservar os metadados do arquivo. No Python 3.3+ copystattambém copia atributos estendidos.
ingyhere