how to copy directory with all file from c:\\xxx\yyy to c:\\zzz\ in python
Asked Answered
P

5

10

I've been trying to use "copytree(src,dst)", however I couldn't since the destination folder should exists at all.Here you can see the small piece of code I wrote:

def copy_dir(src,dest):
    import shutil
    shutil.copytree(src,dest)

copy_dir('C:/crap/chrome/','C:/test/') 

and this is the error I m getting as I expected...

Traceback (most recent call last):
File "C:\Documents and Settings\Administrator\workspace\MMS-Auto\copy.py", line 5, in        <module>
copy_dir('C:/crap/chrome/','C:/test/')   
File "C:\Documents and Settings\Administrator\workspace\MMS-Auto\copy.py", line 3, in copy_dir
shutil.copytree(src,dest)
File "C:\Python27\lib\shutil.py", line 174, in copytree
os.makedirs(dst)
File "C:\Python27\lib\os.py", line 157, in makedirs
mkdir(name, mode)
WindowsError: [Error 183] Cannot create a file when that file already exists:    'C:/test/'

Here is my question is there a way I could achieve the same result without creating my own copytree function?

Thank you in advance.

Pulpiteer answered 6/4, 2012 at 18:20 Comment(2)
What do you want to do? Overwrite the files? Leave the original in place if a file allready exists?Brundage
would be enough to just copy them over, however I might want to add add such a functionality later onPulpiteer
A
1

Look at errno for possible errors. You can use .copytree() first, and then when there is error, use shutil.copy.

From: http://docs.python.org/library/shutil.html#shutil.copytree

If exception(s) occur, an Error is raised with a list of reasons.

So then you can decide what to do with it and implement your code to handle it.

import shutil, errno

def copyFile(src, dst):
    try:
        shutil.copytree(src, dst)
    # Depend what you need here to catch the problem
    except OSError as exc: 
        # File already exist
        if exc.errno == errno.EEXIST:
            shutil.copy(src, dst)
        # The dirtory does not exist
        if exc.errno == errno.ENOENT:
            shutil.copy(src, dst)
        else:
            raise

About .copy(): http://docs.python.org/library/shutil.html#shutil.copy

Copy the file src to the file or directory dst. If dst is a directory, a file with the same basename as src is created (or overwritten) in the directory specified. Permission bits are copied. src and dst are path names given as strings.

Edit: Maybe also look into distutils.dir_util.copy_tree

Adenoma answered 6/4, 2012 at 18:49 Comment(3)
inside the if statement you didn't call anything... what should I add there?Pulpiteer
ok thanks, anyway I'm getting "WindowsError: [Error 183] Cannot create a file when that file already exists: 'C:/test/'"Pulpiteer
Edit: If the file exist EEXIST, then use .copy(), it should overwrite them.Adenoma
F
15

Notice:

distutils has been deprecated and will be removed in Python 3.12. Consider looking for other answers at this question if you are looking for a post-3.12 solution.


Original answer:

I used the distutils package to greater success than the other answers here.

http://docs.python.org/2/distutils/apiref.html#module-distutils.dir_util

The distutils.dir_util.copy_tree function works very similarly to shutil.copytree except that dir_util.copy_tree will just overwrite a directory that exists instead of crashing with an Exception.

Replace:

import shutil
shutil.copytree(src, dst)

with:

import distutils.dir_util
distutils.dir_util.copy_tree(src, dst)
Fanchan answered 28/6, 2013 at 5:53 Comment(1)
DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives from distutils.dir_util import copy_treeDicks
A
1

Look at errno for possible errors. You can use .copytree() first, and then when there is error, use shutil.copy.

From: http://docs.python.org/library/shutil.html#shutil.copytree

If exception(s) occur, an Error is raised with a list of reasons.

So then you can decide what to do with it and implement your code to handle it.

import shutil, errno

def copyFile(src, dst):
    try:
        shutil.copytree(src, dst)
    # Depend what you need here to catch the problem
    except OSError as exc: 
        # File already exist
        if exc.errno == errno.EEXIST:
            shutil.copy(src, dst)
        # The dirtory does not exist
        if exc.errno == errno.ENOENT:
            shutil.copy(src, dst)
        else:
            raise

About .copy(): http://docs.python.org/library/shutil.html#shutil.copy

Copy the file src to the file or directory dst. If dst is a directory, a file with the same basename as src is created (or overwritten) in the directory specified. Permission bits are copied. src and dst are path names given as strings.

Edit: Maybe also look into distutils.dir_util.copy_tree

Adenoma answered 6/4, 2012 at 18:49 Comment(3)
inside the if statement you didn't call anything... what should I add there?Pulpiteer
ok thanks, anyway I'm getting "WindowsError: [Error 183] Cannot create a file when that file already exists: 'C:/test/'"Pulpiteer
Edit: If the file exist EEXIST, then use .copy(), it should overwrite them.Adenoma
A
1

I have a little work around that check whether there is a directory of the same name in the location first before doing the shutil.copytree function. Also it only copies directories with a certain wildcard. Not sure if that is needed to answer the question but I thought to leave it in there.

import sys
import os
import os.path
import shutil 


src="/Volumes/VoigtKampff/Temp/_Jonatha/itmsp_source/"
dst="/Volumes/VoigtKampff/Temp/_Jonatha/itmsp_drop/"


for root, dirs, files in os.walk(src):
    for dir in dirs:
        if dir.endswith('folder'):
            print "directory to be moved: %s" % dir
            s = os.path.join(src, dir)
            d = os.path.join(dst, dir)
            if os.path.isdir(d):
                print "Not copying - because %s is already in %s" % (dir, dst)
            elif not os.path.isdir(d):
                shutil.copytree(s, d)
                print "Copying %s to %s" % (dir, dst)
Arbe answered 6/3, 2013 at 17:27 Comment(0)
B
0

I'm pretty sure this depends on the exact version of python you have, but when i call shutil.copytree.doc i get this:

Recursively copy a directory tree using copy2().

The destination directory must not already exist.

XXX Consider this example code rather than the ultimate tool.

This explains the error you are getting. You could probably use distutils.dir_util.copy_tree instead.

Brundage answered 6/4, 2012 at 18:45 Comment(3)
I don't want to add anything to python itself, although if I won't be able to do it otherwise ,I'll go for itPulpiteer
You mean you don't want to import any library? You imported shutil, you can just as well write import distutils.Brundage
Sorry I misread the python documentation, thank it works... thanks againPulpiteer
U
0

shutil.copytree gained a dirs_exist_ok option in Python 3.8, which allows copying into an existing directory the same as distutils.dir_util.copy_tree:

If dirs_exist_ok is false (the default) and dst already exists, a FileExistsError is raised. If dirs_exist_ok is true, the copying operation will continue if it encounters existing directories, and files within the dst tree will be overwritten by corresponding files from the src tree.

It can be used like so:

import shutil
shutil.copytree(src, dst, dirs_exist_ok=True)
Unblushing answered 14/8 at 6:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.