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 │
└──────────────────┴────────┴───────────┴───────┴────────────────┘
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
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 ☐ ☐ ✔
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@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.
@ 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.
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')
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(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)
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.
"""whileTrue:
copy_buffer = source.read(buffer_size)ifnot 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)
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')
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.
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:
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.
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.
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[:]
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.
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)
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.
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).
Respostas:
shutil
tem muitos métodos que você pode usar. Um dos quais é:Se você usar
os.path
operações, use emcopy
vez decopyfile
.copyfile
vai aceitar apenas cordas .fonte
~
, mas pode lidar com caminhos relativosfonte
copy2(src,dst)
geralmente é mais útil do quecopyfile(src,dst)
porque:dst
ser um diretório (em vez do nome completo do nome do arquivo); nesse caso, o nome da basesrc
é usado para criar o novo arquivo;Aqui está um pequeno exemplo:
fonte
copyfile
é consideravelmente mais rápido do quecopy2
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?/new/dir
houver um diretório existente, consulte o comentário de @ MatthewAlpert./new/dir/
não existir, o Python lançará umIsADirectoryError
, caso contrário, ele copiará o arquivo para/new/dir/
o nome original.Você pode usar uma das funções de cópia do
shutil
pacote:Exemplo:
fonte
No Python, você pode copiar os arquivos usando
shutil
móduloos
módulosubprocess
módulo1) Copiando arquivos usando o
shutil
móduloshutil.copyfile
assinaturashutil.copy
assinaturashutil.copy2
assinaturashutil.copyfileobj
assinatura2) Copiando arquivos usando o
os
móduloos.popen
assinaturaos.system
assinatura3) Copiando arquivos usando o
subprocess
módulosubprocess.call
assinaturasubprocess.check_output
assinaturafonte
['copy', sourcefile, destfile]
sintaxe sempre que possível, especialmente se os parâmetros forem da entrada do usuário.os.popen
está obsoleto por um tempo agora. echeck_output
não retorna o status, mas a saída (que está vazia no caso decopy/cp
)Copiar um arquivo é uma operação relativamente direta, como mostra os exemplos abaixo, mas você deve usar o módulo shutil stdlib para isso.
Se você deseja copiar por nome de arquivo, você pode fazer algo assim:
fonte
shutil.copyfileobj
. Além disso, você não precisatry, finally
lidar 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 osshutil.copyfile
envoltóriosshutil.copyfileobj
.dest
para ser gravável:open(dest, 'wb')
Use o módulo shutil .
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.
fonte
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
fonte
Em primeiro lugar, fiz uma cheatsheet exaustiva dos métodos shutil para sua referência.
Em segundo lugar, explique os métodos de cópia nos exemplos:
Copie recursivamente uma árvore de diretórios inteira enraizada no src, retornando o diretório de destino
fonte
Para arquivos pequenos e usando apenas built-ins python, você pode usar o seguinte recurso:
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.
fonte
.read()
e.write()
são armazenados em buffer por padrão (pelo menos para CPython).open()
IO em buffer, por padrão, não ajuda aqui, porqueread()
é especificado como: 'Se n for negativo ou omitido, leia até EOF'. Isso significa queread()
retorna o conteúdo completo do arquivo como uma sequência.Você poderia usar
os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')
ou como eu fiz isso,
Onde
rawfile
está o nome que eu havia gerado dentro do programa.Esta é uma solução apenas para Linux
fonte
shutil
não está disponível -subprocess.run()
(semshell=True
!) É a melhor alternativa paraos.system()
.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,shutil
e os amigos são mais recomendadas que chamar um programa externo.)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.
fonte
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 comoutput.write(read(n)); output.flush()
onden
está 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.shutil
? Mesmo quando ignoradoshutil
, 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.fonte
call
é inseguro. Consulte os subprocessos sobre isso.No Python 3.5, você pode fazer o seguinte para arquivos pequenos (por exemplo: arquivos de texto, jpegs pequenos):
write_bytes
substituirá o que estava no local de destinofonte
shutil
lida com todos os casos especiais para você e oferece tranqüilidade.Abra o arquivo de origem no modo de leitura e grave no arquivo de destino no modo de gravação.
fonte
.close()
em todos essesopen(...)
s?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
O comando a seguir é usado para Copiar Arquivo com Informações MetaData
fonte
copy
entãocopystat
para preservar os metadados do arquivo. No Python 3.3+copystat
também copia atributos estendidos.