How do you copy files from one location to another?

J

John Salerno

Based on what I've read, it seems os.rename is the proper function to
use, but I'm a little confused about the syntax. Basically I just want
to write a simple script that will back up my saved game files when I
run it. So I want it to copy a set of files/directories from a
location on my C:\ drive to another directory on my E:\ drive. I don't
want to rename or delete the originals, just move them. I also want
them to automatically overwrite whatever already happens to be in the
location on the E:\ drive.

Is os.rename the proper function for this? Mainly I was because the
Module Index says this:

"On Windows, if dst already exists, OSError will be raised even if it
is a file.."

so it sounds like I can't move the files to a location where those
file names already exist.
 
A

Andrew Berg

"On Windows, if dst already exists, OSError will be raised even if it
is a file.."
If you try to create a file or directory that already exists on Windows,
you'll get a WindowsError with error code 183:Traceback (most recent call last):
File "<stdin>", line 1, in <module>
WindowsError: [Error 183] Cannot create a file when that file already
exists: 'C:\\common\\games'

I'm pretty sure you have to delete the existing file before you can
"overwrite" it. You can try to write the file and delete the file and
try again in an except OSError block (this will catch WindowsError as
well since it's a subclass of OSError, and it will catch similar errors
on other platforms).
 
G

Gregory Ewing

John said:
I want it to copy a set of files/directories from a
location on my C:\ drive to another directory on my E:\ drive. I don't
want to rename or delete the originals,

It sounds like shutil.copy() is what you want, or one of the
other related functions in the shutil module.
 
T

Tim Golden

Based on what I've read, it seems os.rename is the proper function to
use, but I'm a little confused about the syntax. Basically I just want
to write a simple script that will back up my saved game files when I
run it. So I want it to copy a set of files/directories from a
location on my C:\ drive to another directory on my E:\ drive. I don't
want to rename or delete the originals, just move them. I also want
them to automatically overwrite whatever already happens to be in the
location on the E:\ drive.

Is os.rename the proper function for this? Mainly I was because the
Module Index says this:

"On Windows, if dst already exists, OSError will be raised even if it
is a file.."

so it sounds like I can't move the files to a location where those
file names already exist.

For a Windows-only Q&D, you could use the pywin32 win32file module
which exposes the MoveFileEx[W] API:

<code>
import win32file

win32file.MoveFileExW (
"c:/temp/blah.txt",
"c:/temp/blah2.txt",
win32file.MOVEFILE_REPLACE_EXISTING
)

</code>

TJG
 
J

John Salerno

It sounds like shutil.copy() is what you want, or one of the
other related functions in the shutil module.


shutil.copy(src, dst)
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.



This looks promising! But can src be a directory, or does it have to
be a file? For my purposes (copying a saved games folder), I don't
really need to specify particular files to copy, I just need to copy
the entire Saved Games directory, so that's what would be my src
argument if allowed.

Also, the directory I want to copy also contains a directory. Will the
contents of that directory also be copied, or do I have to do some
kind of walk-through of the directory manually?
 
H

Heather Brown

Based on what I've read, it seems os.rename is the proper function to
use, but I'm a little confused about the syntax. Basically I just want
to write a simple script that will back up my saved game files when I
run it. So I want it to copy a set of files/directories from a
location on my C:\ drive to another directory on my E:\ drive. I don't
want to rename or delete the originals, just move them. I also want
them to automatically overwrite whatever already happens to be in the
location on the E:\ drive.

Is os.rename the proper function for this? Mainly I was because the
Module Index says this:

"On Windows, if dst already exists, OSError will be raised even if it
is a file.."

so it sounds like I can't move the files to a location where those
file names already exist.

You keep saying 'move' when you want 'copy.' Even if os.rename would
work across drives (it doesn't, on Windows), it still would be removing
the original. Similarly with move.

As Greg mentioned, you want shutil.copy(), not move nor rename.

DaveA
 
T

Terry Reedy

This looks promising! But can src be a directory, or does it have to
be a file? For my purposes (copying a saved games folder), I don't
really need to specify particular files to copy, I just need to copy
the entire Saved Games directory, so that's what would be my src
argument if allowed.

If you follow the second part of Greg's suggestion 'or one of the other
related function in the shutil module', you will find copytree()
"Recursively copy an entire directory tree rooted at src. "
Also, the directory I want to copy also contains a directory. Will the
contents of that directory also be copied, or do I have to do some
kind of walk-through of the directory manually?

If you want more control of which files to copy, between 1 and all, look
as os.walk and the glob module.
 
J

John Salerno

If you follow the second part of Greg's suggestion 'or one of the other
related function in the shutil module', you will find copytree()
"Recursively copy an entire directory tree rooted at src. "

Yeah, but shutil.copytree says:

"The destination directory, named by dst, must not already exist"

which again brings me back to the original problem. All I'm looking
for is a simple way to copy files from one location to another,
overwriting as necessary, but there doesn't seem to be a single
function that does just that.
 
E

Ethan Furman

John said:
Yeah, but shutil.copytree says:

"The destination directory, named by dst, must not already exist"

which again brings me back to the original problem. All I'm looking
for is a simple way to copy files from one location to another,
overwriting as necessary, but there doesn't seem to be a single
function that does just that.

If you don't mind deleting what's already there:

shutil.rmtree(...)
shutil.copytree(...)

If you do mind, roll your own (or borrow ;):

8<-------------------------------------------------------------------
#stripped down and modified version from 2.7 shutil (not tested)
def copytree(src, dst):
names = os.listdir(src)
if not os.path.exists(dst): # no error if already exists
os.makedirs(dst)
errors = []
for name in names:
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
try:
if os.path.isdir(srcname):
copytree(srcname, dstname, symlinks, ignore)
else:
copy2(srcname, dstname)
except (IOError, os.error), why:
errors.append((srcname, dstname, str(why)))
# catch the Error from the recursive copytree so that we can
# continue with other files
except Error, err:
errors.extend(err.args[0])
if errors:
raise Error(errors)
8<-------------------------------------------------------------------

~Ethan~
 
J

John Salerno

Yeah, but shutil.copytree says:
"The destination directory, named by dst, must not already exist"
which again brings me back to the original problem. All I'm looking
for is a simple way to copy files from one location to another,
overwriting as necessary, but there doesn't seem to be a single
function that does just that.

If you don't mind deleting what's already there:

shutil.rmtree(...)
shutil.copytree(...)

If you do mind, roll your own (or borrow ;):

8<-------------------------------------------------------------------
#stripped down and modified version from 2.7 shutil (not tested)
def copytree(src, dst):
     names = os.listdir(src)
     if not os.path.exists(dst):  # no error if already exists
         os.makedirs(dst)
     errors = []
     for name in names:
         srcname = os.path.join(src, name)
         dstname = os.path.join(dst, name)
         try:
             if os.path.isdir(srcname):
                 copytree(srcname, dstname, symlinks, ignore)
             else:
                 copy2(srcname, dstname)
         except (IOError, os.error), why:
             errors.append((srcname, dstname, str(why)))
         # catch the Error from the recursive copytree so that we can
         # continue with other files
         except Error, err:
             errors.extend(err.args[0])
     if errors:
         raise Error(errors)
8<-------------------------------------------------------------------

~Ethan~

Thanks. Deleting what is already there is not a problem, I was just
hoping to have it overwritten without any extra steps, but that's no
big deal.
 
M

Michael Hrivnak

Python is great for automating sysadmin tasks, but perhaps you should
just use rsync for this. It comes with the benefit of only copying
the changes instead of every file every time.

"rsync -a C:\source E:\destination" and you're done.

Michael
 
T

Terry Reedy

Python is great for automating sysadmin tasks, but perhaps you should
just use rsync for this. It comes with the benefit of only copying
the changes instead of every file every time.

"rsync -a C:\source E:\destination" and you're done.

Perhaps 'synctree' would be a candidate for addition to shutil.

If copytree did not prohibit an existing directory as destination, it
could be used for synching with an 'ignore' function.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top