views:

484

answers:

5

I've been doing this all the time:

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

Until today I started to look into pywin32 modules, then I saw functions like win32file.CopyFiles(), but then I found it may not support copying files to a directory. Maybe this functionality is hidden somewhere, but I haven't found it yet.

I've also tried "glob" and "shutil" combination, but "glob" is incredibly slow if there are many files.

So, how do you emulate this Windows command with Python?

copy 123*.xml out_folder\. /y
+3  A: 

Look at glob and shutil before going any further.

Forking a subprocess to copy a file is relatively inefficient. Using shutil will be more efficient.

S.Lott
+1  A: 

The following code provides a portable implementation.

Note that I'm using iglob (added in Python 2.5) which creates a generator, so it does not load the entire list of files in memory first (which is what glob does).

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")

Additional documentation:

Frederik
why all these troubles with `copyfile`? why not just use `copy`?
SilentGhost
Why indeed. I've changed the example to use copy instead of copyfile. This also has the added advantage that permission bits are copied as well.
Frederik
+3  A: 

The below example is fairly naive - doesn't do any checking if something goes wrong, and doesn't create any directories, but might do what you want:

import glob
import shutil

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

See also: http://timgolden.me.uk/python/win32_how_do_i/copy-a-file.html

Using win32file/SHFileOperation copy seems to be more functional, but aren't as portable and are more complicated to use.

David Morrissey
+1  A: 

"glob" is incredibly slow if there are many files.

glob is slow is there are a lot of results because it returns one huge list of all the results in a "big bang" approach. If there are a lot of results this will use a lot of memory and take a long time.

Use iglob instead, as suggested by a previous poster. iglob constructs and returns one iterator object that can be used to loop over the results, without ever having them all in memory at the same time. It's much more efficient if there are a lot of matches.

In general, whenever you write code like "for x in [glob.glob ...]" you should be using glob.iglob instead.

joefis
+1  A: 
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
ghostdog74