¿Cómo copio un archivo en Python?

2479

¿Cómo copio un archivo en Python?

No pude encontrar nada debajo os.

Mate
fuente
117
Parece que cp no es una llamada al sistema y, por lo tanto, no pertenece al módulo os. Es un comando de shell, por lo que se coloca en el módulo shutil.
waldol1

Respuestas:

3013

shutiltiene muchos métodos que puedes usar. Uno de los cuales es:

from shutil import copyfile
copyfile(src, dst)
  • Copie el contenido del archivo llamado src a un archivo llamado dst .
  • La ubicación de destino debe poder escribirse; de lo contrario, se generará una excepción IOError .
  • Si dst ya existe, será reemplazado.
  • Los archivos especiales como dispositivos de caracteres o de bloque y tuberías no se pueden copiar con esta función.
  • Con copy , src y dst son nombres de ruta dados como cadenas .

Si usa os.pathoperaciones, use en copylugar de copyfile. copyfilese acepta solamente cadenas .

Swati
fuente
147
¿Cuál es la diferencia entre copy y copyfile?
Matt
387
en copia (src, dst) el dst puede ser un directorio.
Owen
41
Tenga en cuenta que no todos los metadatos se copiarán, dependiendo de su plataforma.
Kevin Horn
12
Tenga en cuenta que no es una operación atómica. Tenga cuidado al usarlo en una aplicación roscada.
waterbyte
44
Tenga en cuenta que no puede manejar abreviaturas como ~, pero puede tratar con rutas relativas
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
fuente
732

copy2(src,dst)A menudo es más útil que copyfile(src,dst)porque:

  • permite dstser un directorio (en lugar del nombre completo del archivo de destino), en cuyo caso el nombre base de srcse usa para crear el nuevo archivo;
  • conserva la modificación original y la información de acceso (mtime y atime) en los metadatos del archivo (sin embargo, esto viene con una ligera sobrecarga).

Aquí hay un breve ejemplo:

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
fuente
19
Estoy tratando de copiar aleatoriamente 100k archivos de 1 millón de archivos. copyfilees considerablemente más rápido quecopy2
Vijay
44
¿estoy en lo cierto al suponer que shutil.copy2('/dir/file.ext', '/new/dir/')(con una barra inclinada después de la ruta de destino) eliminará la ambigüedad sobre si copiar a un nuevo archivo llamado "dir" o colocar el archivo en un directorio con ese nombre?
Zak
1
@Vijay Creo que esta sobrecarga se debe a la copia de los metadatos.
Jonathan H
@Zak No hay ambigüedad si /new/dirhay un directorio existente, vea el comentario de @ MatthewAlpert.
Jonathan H
@Zak Tienes razón, agregar una barra al final elimina la ambigüedad. Si /new/dir/no existe, Python arrojará un IsADirectoryErrorarchivo; de lo contrario, copiará el archivo /new/dir/con el nombre original.
martonbognar
125

Puede usar una de las funciones de copia del shutilpaquete:

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━
La función conserva los apoyos acepta copias otras
                      directorio de permisos dest. archivo de metadatos de obj  
"" "" "" "" "" "" "" "" "" "" " "" "" "" "" "" "" "" "" "" "
shutil.copy               ✔ ✔ ☐ ☐
 shutil.copy2              ✔ ✔ ☐ ✔
 shutil.copyfile           ☐ ☐ ☐ ☐
 shutil.copyfileobj        ☐ ☐ ✔ ☐
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Ejemplo:

import shutil
shutil.copy('/etc/hostname', '/var/tmp/testhostname')
maxschlepzig
fuente
10
Solo por curiosidad, ¿cómo generaste esa tabla?
lightalchemist
16
@lightalchemist Acabo de usar vim como bloc de notas, copié los símbolos Unicode usados ​​de una tabla de wikipedia y copié el resultado en el editor de stackoverflow para el pulido final.
maxschlepzig
3
¿Cómo es esto diferente de otra respuesta 2 años antes? stackoverflow.com/a/30359308/674039
wim
1
@wim, tienes que comparar mi respuesta con la versión 2017 de la respuesta que has vinculado, que era actual cuando publiqué mi respuesta. Principales diferencias: mi respuesta utiliza encabezados de columna mejores / más descriptivos, el diseño de la tabla no distrae, incluye enlaces directos en la documentación y agregué una columna (es decir, 'acepta el archivo obj').
maxschlepzig
44
OKAY. YMMV, pero creo que los cambios cosméticos y las mejoras menores como esa se realizan mejor como ediciones en las respuestas existentes, en lugar de la duplicación de respuestas.
wim
104

En Python, puede copiar los archivos usando


import os
import shutil
import subprocess

1) Copiar archivos usando el shutilmódulo

shutil.copyfile firma

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

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

shutil.copy firma

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

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

shutil.copy2 firma

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

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

shutil.copyfileobj firma

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) Copiar archivos usando el osmódulo

os.popen firma

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 firma

os.system(command)


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

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

3) Copiar archivos usando el subprocessmódulo

subprocess.call firma

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 firma

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
fuente
99
El uso de comandos de cadena única es un mal estilo de codificación (flexibilidad, confiabilidad y seguridad); en su lugar, use la ['copy', sourcefile, destfile]sintaxis siempre que sea posible, especialmente si los parámetros provienen de la entrada del usuario.
Marcel Waldvogel
8
¿Por qué enumera tantas alternativas malas a las funciones de copia shutil?
maxschlepzig
66
shutil está integrado, no es necesario proporcionar alternativas no portátiles. La respuesta podría mejorarse realmente eliminando las soluciones dependientes del sistema, y ​​después de esa eliminación, esta respuesta es solo una copia de las respuestas existentes / una copia de la documentación.
Jean-François Fabre
3
os.popenestá en desuso por un tiempo ahora. y check_outputno devuelve el estado sino la salida (que está vacía en el caso de copy/cp)
Jean-François Fabre
2
shutil en realidad no copia archivos. Hay una gran advertencia en la parte superior de los documentos . "esto significa que el propietario y el grupo del archivo se pierden, así como las ACL. En Mac OS, la bifurcación de recursos y otros metadatos no se usan. Esto significa que se perderán los recursos y el tipo de archivo y los códigos de creador no serán correctos. En Windows, los propietarios de archivos, las ACL y las secuencias de datos alternativas no se copian ".
gman
96

Copiar un archivo es una operación relativamente sencilla como se muestra en los ejemplos a continuación, pero en su lugar debería usar el módulo shutil stdlib para eso.

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)

Si desea copiar por nombre de archivo, puede hacer algo como esto:

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.
fuente
25
Hace un tiempo noté que el módulo se llama shutil (singular) y no shutils (plural), y de hecho está en Python 2.3. Sin embargo, dejo esta función aquí como ejemplo.
pi.
44
Copiar el contenido de un archivo es una operación sencilla. Copiar el archivo con sus metadatos es cualquier cosa menos sencillo, incluso más si quieres ser multiplataforma.
LaC
3
Cierto. Mirando los documentos de shutil, la función copyfile tampoco copiará metadatos.
pi.
3
Sí, no estoy seguro de por qué no copiarías la fuente shutil.copyfileobj. Además, no tiene try, finallyque manejar el cierre de los archivos después de las excepciones. Sin embargo, diría que su función no debería ser responsable de abrir y cerrar los archivos. Eso debería ir en una función de envoltura, como cómo se shutil.copyfileenvuelve shutil.copyfileobj.
ErlVolton
2
El código anterior debe especificar destque se puede escribir:open(dest, 'wb')
user1016274
69

Utiliza el módulo shutil .

copyfile(src, dst)

Copie el contenido del archivo llamado src a un archivo llamado dst. La ubicación de destino debe poder escribirse; de lo contrario, se generará una excepción IOError. Si dst ya existe, será reemplazado. Los archivos especiales como dispositivos de caracteres o de bloque y tuberías no se pueden copiar con esta función. src y dst son nombres de ruta dados como cadenas.

Eche un vistazo a filesys para todas las funciones de manejo de archivos y directorios disponibles en los módulos estándar de Python.

Airsource Ltd
fuente
shutil en realidad no copia archivos. Hay una gran advertencia en la parte superior de los documentos . "esto significa que el propietario y el grupo del archivo se pierden, así como las ACL. En Mac OS, la bifurcación de recursos y otros metadatos no se usan. Esto significa que se perderán los recursos y el tipo de archivo y los códigos de creador no serán correctos. En Windows, los propietarios de archivos, las ACL y las secuencias de datos alternativas no se copian ".
gman
47

Ejemplo de copia de directorio y archivo - De Tim Golden's Python Stuff:

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
fuente
24

En primer lugar, hice una exhaustiva hoja de trucos de métodos shutil para su referencia.

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

En segundo lugar, explique los métodos de copia en ejemplos:

  1. shutil.copyfileobj(fsrc, fdst[, length]) manipular objetos abiertos
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) Copiar y renombrar
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() Copie sin preseleccionar los metadatos
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 preseleccionando los metadatos
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 un árbol de directorios completo enraizado en src, devolviendo el directorio de destino

Cálculo
fuente
1
shutil en realidad no copia archivos. Hay una gran advertencia en la parte superior de los documentos . "esto significa que el propietario y el grupo del archivo se pierden, así como las ACL. En Mac OS, la bifurcación de recursos y otros metadatos no se usan. Esto significa que se perderán los recursos y el tipo de archivo y los códigos de creador no serán correctos. En Windows, los propietarios de archivos, las ACL y las secuencias de datos alternativas no se copian ".
gman
19

Para archivos pequeños y que usan solo elementos integrados de Python, puede usar el siguiente one-liner:

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

Como @maxschlepzig mencionó en los comentarios a continuación, esta no es la forma óptima para aplicaciones donde el archivo es demasiado grande o cuando la memoria es crítica, por lo tanto, se debe preferir la respuesta de Swati .

yellow01
fuente
3
Esto lee el archivo fuente completo en la memoria antes de volverlo a escribir. Por lo tanto, esto desperdicia innecesariamente memoria para todas las operaciones de copia de archivos, excepto las más pequeñas.
maxschlepzig
1
¿Es eso cierto? Creo .read()y .write()están almacenados de forma predeterminada (al menos para CPython).
sonora
@soundstripe, por supuesto, esto es cierto. El hecho de que el objeto de archivo devuelto por open()IO amortiguado, por defecto no le ayuda aquí, porque read()se especifica como: 'Si n es negativo u omitido, lea hasta EOF'. Eso significa que read()devuelve el contenido completo del archivo como una cadena.
maxschlepzig
@maxschlepzig Entiendo tu punto y admito que no estaba al tanto. La razón por la que proporcioné esta respuesta fue en caso de que alguien quisiera hacer una copia de archivo simple usando solo elementos integrados, sin necesidad de importarle un módulo. Por supuesto, la optimización de la memoria no debería ser una preocupación si desea esta opción. De todos modos, gracias por aclarar eso. Actualicé la respuesta en consecuencia.
yellow01
14

Podrías usar os.system('cp nameoffilegeneratedbyprogram /otherdirectory/')

o como lo hice

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

¿Dónde rawfileestá el nombre que había generado dentro del programa?

Esta es una solución única para Linux

marca
fuente
10
Esto no es portátil e innecesario, ya que puede usar shutil.
Corey Goldberg
44
Incluso cuando shutilno está disponible, subprocess.run() ( shell=True¡ sin !) Es la mejor alternativa a os.system().
maxschlepzig
1
shutil es más portátil
Hiadore
1
subprocess.run()según lo sugerido por @maxschlepzig es un gran paso adelante al llamar a programas externos. Sin embargo, para mayor flexibilidad y seguridad, use la ['cp', rawfile, 'rawdata.dat']forma de pasar la línea de comando. (Sin embargo, para copiar, shutily se recomiendan amigos antes de llamar a un programa externo).
Marcel Waldvogel
2
intente eso con nombres de archivo con espacios en él.
Jean-François Fabre
11

Para archivos grandes, lo que hice fue leer el archivo línea por línea y leer cada línea en una matriz. Luego, una vez que la matriz alcance un cierto tamaño, agréguela a un nuevo archivo.

for line in open("file.txt", "r"):
    list.append(line)
    if len(list) == 1000000: 
        output.writelines(list)
        del list[:]
Ytpillai
fuente
2
Esto parece un poco redundante ya que el escritor debe manejar el almacenamiento en búfer. for l in open('file.txt','r'): output.write(l)debería funcionar encontrar; simplemente configure el búfer de flujo de salida según sus necesidades. o puede ir por los bytes haciendo un bucle de prueba con output.write(read(n)); output.flush()dónde nestá la cantidad de bytes que desea escribir a la vez. ambos tampoco tienen una condición para verificar cuál es un bono.
posee el
1
Sí, pero pensé que tal vez esto podría ser más fácil de entender porque copia líneas enteras en lugar de partes de ellas (en caso de que no sepamos cuántos bytes tiene cada línea).
ytpillai
Muy cierto. La codificación para la enseñanza y la codificación para la eficiencia son muy diferentes.
posee el
1
mirando la fuente: Writelines llama a write, hg.python.org/cpython/file/c6880edaf6f3/Modules/_io/bytesio.c . Además, la secuencia de archivos ya está abierta, por lo que escribir no necesitaría volver a abrirla cada vez.
posee
2
Esto es horrible Hace un trabajo innecesario sin ninguna buena razón. No funciona para archivos arbitrarios. La copia no es idéntica en bytes si la entrada tiene terminaciones de línea inusuales en sistemas como Windows. ¿Por qué crees que esto podría ser más fácil de entender que una llamada a una función de copia shutil? Incluso cuando se ignora shutil, un simple ciclo de lectura / escritura en bloque (usando IO sin búfer) es sencillo, sería eficiente y tendría mucho más sentido que esto, y por lo tanto seguramente es más fácil de enseñar y comprender.
maxschlepzig
11
from subprocess import call
call("cp -p <file> <file>", shell=True)
bucear profundo
fuente
10
Esto depende de la plataforma, por lo que no usaría es.
Kevin Meier
55
Tal calles inseguro. Consulte el documento de subprocesos al respecto.
buhtz
2
Esto no es portátil e innecesario, ya que puede usar shutil.
Corey Goldberg
2
¿Por qué Python, entonces?
Baris Demiray
Quizás detecte el sistema operativo antes de comenzar (ya sea DOS o Unix, porque esos son los dos más utilizados)
MilkyWay90
8

A partir de Python 3.5 , puede hacer lo siguiente para archivos pequeños (es decir: archivos de texto, pequeños archivos JPEG):

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 sobrescribirá lo que haya en la ubicación del destino

Bagazo
fuente
2
Y luego alguien usa el código (accidental o intencionalmente) en un archivo grande ... El uso de funciones de shutilmaneja todos los casos especiales para usted y le da tranquilidad.
Marcel Waldvogel
44
al menos no repite las mismas soluciones una y otra vez.
Jean-François Fabre
6
open(destination, 'wb').write(open(source, 'rb').read())

Abra el archivo de origen en modo de lectura y escriba en el archivo de destino en modo de escritura.

S471
fuente
1
La idea es buena y el código es hermoso, pero una función adecuada de copy () puede hacer más cosas, como copiar atributos (+ x bit) o, por ejemplo, eliminar los bytes ya copiados en caso de que se encuentre una condición de disco lleno .
Raúl Salinas-Monteagudo
1
Todas las respuestas necesitan explicación, incluso si es una oración. Ninguna explicación establece un mal precedente y no es útil para comprender el programa. ¿Qué pasaría si un novato completo de Python apareciera y viera esto, quisiera usarlo, pero no pudiera porque no lo entienden? Desea ser útil para todos en sus respuestas.
connectyourcharger
1
¿No es eso lo que falta .close()en todos esos open(...)s?
luckydonald
No es necesario .close (), ya que NO ESTAMOS ALMACENANDO el objeto puntero de archivo en ninguna parte (ni para el archivo src ni para el archivo de destino).
S471
1
El mismo enfoque de pérdida de memoria subóptima que la respuesta de yellow01 .
maxschlepzig
-3

Python proporciona funciones integradas para copiar fácilmente archivos utilizando las utilidades Shell del sistema operativo.

El siguiente comando se utiliza para copiar el archivo

shutil.copy(src,dst)

El siguiente comando se utiliza para copiar archivos con información de metadatos

shutil.copystat(src,dst)
Savai Maheshwari
fuente
Debe ejecutar copyentonces copystatpara preservar los metadatos del archivo. En Python 3.3+ copystattambién copia atributos extendidos.
ingyhere