Ejecute el siguiente código desde un directorio que contiene un directorio llamado bar(que contiene uno o más archivos) y un directorio llamado baz(que también contiene uno o más archivos). Asegúrese de que no haya un directorio llamado foo.
import shutil
shutil.copytree('bar', 'foo')
shutil.copytree('baz', 'foo')
Fallará con:
$ python copytree_test.py
Traceback (most recent call last):
File "copytree_test.py", line 5, in <module>
shutil.copytree('baz', 'foo')
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/shutil.py", line 110, in copytree
File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/os.py", line 172, in makedirs
OSError: [Errno 17] File exists: 'foo'
Quiero que esto funcione de la misma manera que si hubiera escrito:
$ mkdir foo
$ cp bar/* foo/
$ cp baz/* foo/
¿Es necesario utilizar shutil.copy()para copiar cada archivo en baza foo? (¿Después de que ya he copiado el contenido de 'bar' en 'foo' con shutil.copytree()?) ¿O hay una manera más fácil / mejor?

shutil.copytree()el comportamiento para permitir la escritura en un directorio existente, pero hay algunos detalles de comportamiento que deben acordarse.Respuestas:
Esta limitación del estándar
shutil.copytreeparece arbitraria y molesta. Solución alterna:Tenga en cuenta que no es totalmente coherente con el estándar
copytree:symlinksyignoreparámetros para el directorio raíz delsrcárbol;shutil.Errorerrores en el nivel raíz desrc;shutil.Errorpara ese subárbol en lugar de intentar copiar otros subárboles y generará un solo combinadoshutil.Error.fuente
shutil.copytreehace unos.makedirs(dst)al principio. Ninguna parte del código realmente tendría un problema con un directorio preexistente. Esto necesita ser cambiado. Al menos proporcione unexist_ok=Falseparámetro para la llamadadef copyTree( src, dst, symlinks=False, ignore=None): for item in os.listdir(src): s = os.path.join(src, item) d = os.path.join(dst, item) if os.path.isdir(s): if os.path.isdir(d): self.recursiveCopyTree(s, d, symlinks, ignore) else: shutil.copytree(s, d, symlinks, ignore) else: shutil.copy2(s, d)distutils.dir_util.copy_tree(), que también reside en stdlib, no tiene esa restricción y en realidad se comporta como se esperaba. Dado eso, no hay una razón convincente para intentar desenrollar su propia implementación ( ... normalmente rota ). La respuesta de Brendan Abel debería ser absolutamente la solución aceptada ahora.Aquí hay una solución que forma parte de la biblioteca estándar:
Ver esta pregunta similar.
Copie el contenido del directorio en un directorio con python
fuente
distutils.errors.DistutilsInternalError: mkpath: 'name' must be a string, es decir, no aceptaPosixPath. Necesitarástr(PosixPath). Lista de deseos para mejorar. Aparte de este asunto, prefiero esta respuesta.Pathobjeto heredestr, supongo, como la mayoría de las implementaciones anteriores de objetos de ruta orientados a objetos ...distutils.dir_util.copy_tree()se considera un detalle de implementación de distutils y no se recomienda para uso público. La solución real debería sershutil.copytree()mejorar / ampliar para comportarse más comodistutils.dir_util.copy_tree(), pero sin sus defectos. Mientras tanto, seguiré usando funciones de ayuda personalizadas similares a algunas de las que se proporcionan en otras respuestas.En una ligera mejora en la respuesta de atzz a la función donde la función anterior siempre intenta copiar los archivos de origen a destino.
En mi implementación anterior
Estoy usando la función anterior junto con scons build. Me ayudó mucho ya que cada vez que compilo no necesito copiar todo el conjunto de archivos ... sino solo los archivos que se modifican.
fuente
if not os.path.exists(d) or os.stat(s).st_mtime - os.stat(d).st_mtime > 1:Una fusión inspirada en atzz y Mital Vora:
fuente
[x for x in lst if x not in excl]esto no hace lo mismo que copytree, que utiliza la coincidencia de patrón global. en.wikipedia.org/wiki/Glob_(programming)Python 3.8 introdujo el
dirs_exist_okargumento parashutil.copytree:Por lo tanto, con Python 3.8+ esto debería funcionar:
fuente
dirs_exist_ok=Falsepor defecto en copytree, ¿no fallará el primer intento de copia?dirs_exist_okde la primera llamada para ilustrar la diferencia (y porque el directorio aún no existe en el ejemplo de OP), pero, por supuesto, puede usarlo si lo desea.los documentos declaran explícitamente que el directorio de destino no debería existir :
Creo que su mejor opción es
os.walkel segundo y todos los directorios,copy2directorios y archivos consecuentes y hacer máscopystatpara directorios. Después de todo, eso es precisamente locopytreeque se explica en los documentos. O podríacopyycopystatcada directorio / archivo y enos.listdirlugar deos.walk.fuente
Esto está inspirado en la mejor respuesta original proporcionada por atzz, acabo de agregar reemplazar la lógica de archivo / carpeta. Por lo tanto, en realidad no se fusiona, pero elimina el archivo / carpeta existente y copia el nuevo:
Descomente el rmtree para que sea una función de movimiento.
fuente
Aquí está mi versión de la misma tarea ::
fuente
Aquí hay una versión inspirada en este hilo que imita más de cerca
distutils.file_util.copy_file.updateonlyes un bool si es True, solo copiará archivos con fechas modificadas más recientes que los archivos existentes adstmenos que se enumeren en losforceupdatecuales se copiará independientemente.ignoreyforceupdateesperar listas de nombres de archivos o carpetas / nombres de archivos relativossrcy aceptar comodines de estilo Unix similares aglobofnmatch.La función devuelve una lista de archivos copiados (o se copiarían si
dryrunfuera Verdadero).fuente
La solución anterior tiene algún problema que
srcpuede sobrescribirsedstsin ninguna notificación o excepción.Agrego un
predict_errormétodo para predecir errores antes de copiar.copytreeprincipalmente basado en la versión de Cyrille Pontvieux.Lo mejor es usar
predict_errorpara predecir todos los errores al principio, a menos que desee ver una excepción generada una por otra cuando se ejecutecopytreehasta corregir todos los errores.fuente
Aquí está mi pase al problema. Modifiqué el código fuente de copytree para mantener la funcionalidad original, pero ahora no se produce ningún error cuando el directorio ya existe. También lo cambié para que no sobrescriba los archivos existentes, sino que mantenga ambas copias, una con un nombre modificado, ya que esto era importante para mi aplicación.
fuente
Prueba esto:
fuente
Aquí hay una versión que espera una
pathlib.Pathentrada.Tenga en cuenta que esta función requiere Python 3.6, que es la primera versión de Python donde
os.listdir()admite objetos de tipo ruta como entrada. Si necesita admitir versiones anteriores de Python, puede reemplazarlistdir(src)porlistdir(str(src)).fuente
Supongo que la forma más rápida y simple sería hacer que Python llame a los comandos del sistema ...
ejemplo..
Tar y gzip el directorio .... descomprima y descomprima el directorio en el lugar deseado.
yah
fuente