Copia de archivos de Python para Windows con soporte de comodines

He estado haciendo esto todo el tiempo

result = subprocess.call(['copy', '123*.xml', 'out_folder\\.', '/y']) if result == 0: do_something() else: do_something_else() 

Hasta hoy comencé a buscar en los módulos pywin32, luego vi funciones como win32file.CopyFiles (), pero luego descubrí que es posible que no admita copiar archivos a un directorio. Tal vez esta funcionalidad esté oculta en algún lugar, pero aún no la he encontrado.

También he probado la combinación “glob” y “shutil”, pero “glob” es increíblemente lenta si hay muchos archivos.

Entonces, ¿cómo emulas este comando de Windows con Python?

 copy 123*.xml out_folder\. /y 

El siguiente código proporciona una implementación portátil.

Tenga en cuenta que estoy usando iglob (agregado en Python 2.5) que crea un generador, por lo que primero no carga la lista completa de archivos en la memoria (que es lo que hace glob).

 from glob import iglob from shutil import copy from os.path import join def copy_files(src_glob, dst_folder): for fname in iglob(src_glob): copy(fname, join(dst_folder, fname)) if __name__=='__main__': copy_files("123*.xml", "out_folder") 

Documentación adicional:

  • shutil.copy
  • os.path.join
  • glob.iglob

El siguiente ejemplo es bastante ingenuo: no comprueba si algo sale mal y no crea ningún directorio, pero puede hacer lo que quiera:

 import glob import shutil for path in glob.iglob('123*.xml'): shutil.copy(path, 'out_folder/%s' % path) 

Véase también: http://timgolden.me.uk/python/win32_how_do_i/copy-a-file.html

El uso de la copia de win32file / SHFileOperation parece ser más funcional, pero no es tan portátil y es más complicado de usar.

Mira glob y shutil antes de seguir adelante.

Bifurcar un subproceso para copiar un archivo es relativamente ineficiente. Usar shutil será más eficiente.

“glob” es increíblemente lento si hay muchos archivos.

glob es lento si hay muchos resultados porque devuelve una lista enorme de todos los resultados en un enfoque de “big bang”. Si hay muchos resultados, se utilizará mucha memoria y tomará mucho tiempo.

Utilice iglob en su lugar, como lo sugiere un póster anterior. iglob construye y devuelve un objeto iterador que se puede usar para repasar los resultados, sin tenerlos todos en la memoria al mismo tiempo. Es mucho más eficiente si hay muchos partidos.

En general, cada vez que escriba un código como “para x en [glob.glob …]” debería usar glob.iglob en su lugar.

 import os import shutil path=os.path.join("/home","mypath") destination=os.path.join("/destination","dir") for r,d,f in os.walk(path): for files in f: if files.endswith(".xml"): try: shutil.copy(os.path.join(r,files) , destination) except IOError,e: print e