How to move a file in Python?
Solution 1
os.rename()
, os.replace()
, or shutil.move()
All employ the same syntax:
import os
import shutil
os.rename("path/to/current/file.foo", "path/to/new/destination/for/file.foo")
os.replace("path/to/current/file.foo", "path/to/new/destination/for/file.foo")
shutil.move("path/to/current/file.foo", "path/to/new/destination/for/file.foo")
Note that you must include the file name (file.foo
) in both the source and destination arguments. If it is changed, the file will be renamed as well as moved.
Note also that in the first two cases the directory in which the new file is being created must already exist. On Windows, a file with that name must not exist or an exception will be raised, but os.replace()
will silently replace a file even in that occurrence.
As has been noted in comments on other answers, shutil.move
simply calls os.rename
in most cases. However, if the destination is on a different disk than the source, it will instead copy and then delete the source file.
Solution 2
Although os.rename()
and shutil.move()
will both rename files, the command that is closest to the Unix mv command is shutil.move()
. The difference is that os.rename()
doesn't work if the source and destination are on different disks, while shutil.move()
is files disk agnostic.
Solution 3
After Python 3.4, you can also use pathlib
's class Path
to move file.
from pathlib import Path
Path("path/to/current/file.foo").rename("path/to/new/destination/for/file.foo")
https://docs.python.org/3.4/library/pathlib.html#pathlib.Path.rename
Solution 4
For either the os.rename or shutil.move you will need to import the module. No * character is necessary to get all the files moved.
We have a folder at /opt/awesome called source with one file named awesome.txt.
in /opt/awesome
○ → ls
source
○ → ls source
awesome.txt
python
>>> source = '/opt/awesome/source'
>>> destination = '/opt/awesome/destination'
>>> import os
>>> os.rename(source, destination)
>>> os.listdir('/opt/awesome')
['destination']
We used os.listdir to see that the folder name in fact changed. Here's the shutil moving the destination back to source.
>>> import shutil
>>> shutil.move(destination, source)
>>> os.listdir('/opt/awesome/source')
['awesome.txt']
This time I checked inside the source folder to be sure the awesome.txt file I created exists. It is there :)
Now we have moved a folder and its files from a source to a destination and back again.
Solution 5
This is what I'm using at the moment:
import os, shutil
path = "/volume1/Users/Transfer/"
moveto = "/volume1/Users/Drive_Transfer/"
files = os.listdir(path)
files.sort()
for f in files:
src = path+f
dst = moveto+f
shutil.move(src,dst)
Now fully functional. Hope this helps you.
Edit:
I've turned this into a function, that accepts a source and destination directory, making the destination folder if it doesn't exist, and moves the files. Also allows for filtering of the src files, for example if you only want to move images, then you use the pattern '*.jpg'
, by default, it moves everything in the directory
import os, shutil, pathlib, fnmatch
def move_dir(src: str, dst: str, pattern: str = '*'):
if not os.path.isdir(dst):
pathlib.Path(dst).mkdir(parents=True, exist_ok=True)
for f in fnmatch.filter(os.listdir(src), pattern):
shutil.move(os.path.join(src, f), os.path.join(dst, f))
David542
Updated on January 06, 2022Comments
-
David542 over 2 years
I looked into the Python
os
interface, but was unable to locate a method to move a file. How would I do the equivalent of$ mv ...
in Python?>>> source_files = '/PATH/TO/FOLDER/*' >>> destination_folder = 'PATH/TO/FOLDER' >>> # equivalent of $ mv source_files destination_folder
-
mac10688 about 11 yearsdocs.python.org/2/library/shutil.html This documentation shows that you have you your parameters switched for the shutil.move method.
-
jmontross about 11 yearsI used the destination and source reversed to see that the files moved from the source and then back to it.... I could see how that is unclear.
-
fmalina over 10 years
shutil.move()
usesos.rename()
if the destination is on the current filesystem. Otherwise,shutil.move()
copies the source to destination usingshutil.copy2()
and then removes the source. -
2rs2ts about 10 yearsTake care to realize that
shutil.copy2()
can't copy all file metadata, so if that happens it's like doingcp -p
and thenrm
, I gather. -
Dana almost 10 yearsBe aware: shutil.move in Python 2.7.3 fails if the destination already exists. So if that is possible, either catch the error, or manually remove the file/dir, then do the move.
-
Fabian almost 10 yearsAm I the only one that thinks os.rename is not working for directories? I quote: "If dst is a directory, OSError will be raised."
-
whyisyoung about 9 years
shutil.move
works for directories. You can use relative pathshutil.move(f.name, "tmp/")
or full pathshutil.move(f.name, "/Users/hello/tmp/")
, do not use~
in the path, checked in python2.7.9, Mac OS X. -
Armen Michaeli almost 9 years
~
is a shell construct, and has nothing to do with file paths per se, other than as a misplaced convention. If you really want to involve your home directory, useos.getenv('HOME')
instead, concatenating it with parts of your desired path, if necessary. -
ig0774 almost 9 yearsYou could always use
os.path.expanduser()
to properly expand the '~
' according to os-specific rules. Much neater since%HOME%
isn't always set on Windows. -
c z over 7 yearsIf you want to use
os
thenos.rename
behaves differently on different platforms if the file exists, instead useos.replace
-
Giuseppe Scrivano about 7 years
os.rename
won't handle files across different devices. Useshutil.move
if you are not sure the source and the destination file are on the same device. -
jusopi over 5 yearsif you are using Python3.# you can use the new f-string intrerpolation:
f"{new_path}{f}"
but given that you have no static text in your string, this may be more work.... I've been trying to get into the habit of using f-strings though. -
Zachary Ryan Smith over 5 yearsOn my Mac,
os.rename
would err withOSError: [Errno 2] No such file or directory
, even though it seemed to work fine (except for throwing the error).os.replace
is undefined (python 2.7).shutil.move
seems to work fine -
Jacques Mathieu about 5 yearsNot useless, simply requires more work to get it to move multiple files. You can get file names with
os.path.basename(my_file_path)
and the file directories withos.path.dirname(my_file_path)
. Additionally, it was not made very clear by the OP if he wanted to move multiple files. He mentioned moving only one file in the question, but his example code implied moving multiple files. -
iggy12345 about 5 yearsYou can easily turn this into a filtered move by using fnmatch.filter(), see my edit. Also, its best to use
os.path.join(parent_path, filename)
instead of string concatenation to avoid cross-platform issues -
Bachsau about 5 years@Fabian It works with directories, but the destination can not be an existing directory. If destination is an existing file, it will be replaced. Normally destination should not exist, and if it is a directory, it will not replace that whole directory with something else.
rename
is a simple command with clear semantics. It does not make the assumption to place a file inside a directory if destination is a directory. But you can move whole directories with it. -
Matthew over 4 yearsDo you mean file instead of f?
-
jxramos over 4 yearsI'd like to point out that at least for Windows running
Python 3.7.3
thatshutil.move
respects the file attributes, both created and modified which is really great. This was a folder to folder move on the same disk. It would be really great to run those experiments for each of the commands above and tabulate the attribute preserving behavior across OS platforms and even drives by the looks of it. -
Joshua Schlichting about 4 yearsI believe this would be system dependent. I don't see
mv
being used successfully on a windows operating system. -
Amar over 3 yearsI used it recently in the form of -->
Path("path/to/current/file.foo").rename("path/to/new/destination/for/".joinpath(Path.name))
to move all the *.LNK (shortcut) files to a DUMP directory. Worked like a charm! :D -
capooti over 3 yearsThis works perfectly, but it will fail if you want move the file from one device to another (Invalid cross-device link)
-
Timo over 3 yearsI do not think this is valid for shutil.move:
Note that you must include the file name (file.foo) in both the source and destination arguments.
-
MoonFruit about 3 years@Amar maybe this is better.
Path("path/to/current/file.foo").rename(Path("path/to/new/destination/for") / Path.name))
-
Pranav Gupta almost 3 yearsWhy to call external process when python has API for that ?
-
LightCC over 2 years@JoshuaSchlichting It would be more shell dependent than platform type. For example, on Windows this will work fine in a Git Bash terminal, but not using Cmd.
-
Joshua Schlichting over 2 years@LightCC Good catch! Thanks!
-
LightCC over 2 yearsI updated the answer with the correct information in the final paragraph rather than a question if it's system dependent.
-
Ludo Schmidt about 2 yearserror in the example. src,dst is reversed !
-
Bob Kline almost 2 years@ig0774 When you wrote "Note also that in the first two cases the directory in which the new file is being created must already exist" I read that as implying that this is not true for the third case. That's wrong, as I found out the hard way. The destination directories must already exist for
shutil.move()
.