How can I do the equivalent of mv
in Python?
mv "path/to/current/file.foo" "path/to/new/destination/for/file.foo"
How can I do the equivalent of mv
in Python?
mv "path/to/current/file.foo" "path/to/new/destination/for/file.foo"
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")
"file.foo"
) must be included in both the source and destination arguments. If it differs between the two, the file will be renamed as well as moved.os.replace()
will silently replace a file even in that occurrence.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.shutil.move
works for directories. You can use relative path shutil.move(f.name, "tmp/")
or full path shutil.move(f.name, "/Users/hello/tmp/")
, do not use ~
in the path, checked in python2.7.9, Mac OS X. –
Titleholder ~
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, use os.getenv('HOME')
instead, concatenating it with parts of your desired path, if necessary. –
Mckenna os.path.expanduser()
to properly expand the '~
' according to os-specific rules. Much neater since %HOME%
isn't always set on Windows. –
Doridoria os
then os.rename
behaves differently on different platforms if the file exists, instead use os.replace
–
Posthaste os.rename
won't handle files across different devices. Use shutil.move
if you are not sure the source and the destination file are on the same device. –
Protagoras os.rename
would err with OSError: [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 –
Montoya 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. –
Amendment Python 3.7.3
that shutil.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. –
Lippmann Note that you must include the file name (file.foo) in both the source and destination arguments.
–
Exergue shutil.move()
. –
Berzelius 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.
shutil.move()
uses os.rename()
if the destination is on the current filesystem. Otherwise, shutil.move()
copies the source to destination using shutil.copy2()
and then removes the source. –
Piranha shutil.copy2()
can't copy all file metadata, so if that happens it's like doing cp -p
and then rm
, I gather. –
Dispute 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
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 –
Pugnacious Path("path/to/current/file.foo").rename(Path("path/to/new/destination/for") / Path.name))
–
Roussillon 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
>>> source = '/opt/awesome/destination'
>>> destination = '/opt/awesome/source'
>>> shutil.move(source, destination)
>>> 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.
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)
You can also turn 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))
os.path.join(parent_path, filename)
instead of string concatenation to avoid cross-platform issues –
Hyperostosis The accepted answer is not the right one, because the question is not about renaming a file into a file, but moving many files into a directory. shutil.move
will do the work, but for this purpose os.rename
is useless (as stated on comments) because destination must have an explicit file name.
os.path.basename(my_file_path)
and the file directories with os.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. –
Supervise Since you don't care about the return value, you can do
import os
os.system("mv src/* dest/")
Also possible with using subprocess.run()
method.
python:
>>> import subprocess
>>> new = "/path/to/destination"
>>> old = "/path/to/new/destination"
>>> process = "mv ..{} ..{}".format(old,new)
>>> subprocess.run(process, shell=True) # do not remember, assign shell value to True.
This will work fine when working on Linux. Windows probably gives error since there is no mv Command.
Based on the answer described here, using subprocess
is another option.
Something like this:
subprocess.call("mv %s %s" % (source_files, destination_folder), shell=True)
I am curious to know the pro's and con's of this method compared to shutil
. Since in my case I am already using subprocess
for other reasons and it seems to work I am inclined to stick with it.
This is dependent on the shell you are running your script in. The mv
command is for most Linux shells (bash, sh, etc.), but would also work in a terminal like Git Bash on Windows. For other terminals you would have to change mv
to an alternate command.
mv
being used successfully on a windows operating system. –
Polyphemus This is solution, which does not enables shell
using mv
.
from subprocess import Popen, PIPE, STDOUT
source = "path/to/current/file.foo",
destination = "path/to/new/destination/for/file.foo"
p = Popen(["mv", "-v", source, destination], stdout=PIPE, stderr=STDOUT)
output, _ = p.communicate()
output = output.strip().decode("utf-8")
if p.returncode:
print(f"E: {output}")
else:
print(output)
import os,shutil
current_path = "" ## source path
new_path = "" ## destination path
os.chdir(current_path)
for files in os.listdir():
os.rename(files, new_path+'{}'.format(f))
shutil.move(files, new_path+'{}'.format(f)) ## to move files from
different disk ex. C: --> D:
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. –
Gerber © 2022 - 2024 — McMap. All rights reserved.
mv
command, python'sshutil.move
has one edge case whereshutil.move
function differs. Go here for full write up. In a nutshell, Python'sshutil.move
will raise an exception (but gnu-coreutilsmv
will not) when your destination is a directory and the directory already has a file with the same name as the source (again for more info see the link provided in the previous sentence). – Torchwood