如何在 Python 中移动文件?

How do I move a file in Python?

提问人:David542 提问时间:1/14/2012 最后编辑:Mateen UlhaqDavid542 更新时间:2/23/2023 访问量:1844893

问:

如何在 Python 中做相当于 mv 的事情?

mv "path/to/current/file.foo" "path/to/new/destination/for/file.foo"
文件 文件处理 python-os

评论

8赞 Trevor Boyd Smith 8/11/2017
对于那些熟悉 gnu-coreutils 的 mv 命令的人来说,Python 有一个函数不同的边缘情况。去这里 完整文章。简而言之,当您的目标是一个目录并且该目录已经有一个与源同名的文件时,Python 的 shutil.move 将引发异常(但 gnu-coreutils mv 不会)(有关更多信息,请参阅上一句中提供的链接)。shutil.moveshutil.move
0赞 Javier Palacios 8/9/2023
我觉得编辑一个问题以匹配公认的答案是极其不公平的。该问题没有要求将文件移动到文件中,而是要求将文件移动到目录中

答:

2151赞 ig0774 1/14/2012 #1

os.rename()、os.replace() 或 shutil.move()

它们都采用相同的语法:

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")
  • filename () 必须包含在 source 和 destination 参数中。如果两者不同,则文件将被重命名和移动。"file.foo"
  • 要在其中创建新文件的目录必须已存在。
  • 在 Windows 上,具有该名称的文件不得存在,否则将引发异常,但即使在发生这种情况时,也会以静默方式替换文件。os.replace()
  • shutil.move在大多数情况下只是打电话。但是,如果目标位于与源文件不同的磁盘上,则它将复制源文件,然后删除源文件。os.rename

评论

10赞 Fabian 6/24/2014
我是唯一一个认为os.rename不适用于目录的人吗?我引用:“如果 dst 是一个目录,则将引发 OSError。
63赞 whyisyoung 4/21/2015
shutil.move适用于目录。可以使用相对路径或全路径,不要在路径中使用~,在python2.7.9,Mac OS X中检查过。shutil.move(f.name, "tmp/")shutil.move(f.name, "/Users/hello/tmp/")
7赞 Armen Michaeli 7/24/2015
~是一个 shell 构造,除了作为放错位置的约定之外,与文件路径本身无关。如果您真的想让主目录参与进来,请改用,并在必要时将其与所需路径的一部分连接起来。os.getenv('HOME')
23赞 ig0774 7/24/2015
您始终可以使用根据特定于操作系统的规则正确扩展 ''。更整洁,因为并不总是在 Windows 上设置。os.path.expanduser()~%HOME%
26赞 Giuseppe Scrivano 3/6/2017
os.rename不会跨不同设备处理文件。如果您不确定源文件和目标文件是否在同一设备上,请使用。shutil.move
45赞 jmontross 2/22/2013 #2

对于 或,您需要导入模块。 移动所有文件不需要任何字符。os.renameshutil.move*

我们在名为 source 有一个文件夹,其中包含一个名为 awesome.txt 的文件。/opt/awesome

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']

我们曾经看到文件夹名称实际上发生了变化。 这是将目标移回源。os.listdirshutil

>>> import shutil
>>> source = '/opt/awesome/destination' 
>>> destination = '/opt/awesome/source'
>>> shutil.move(source, destination)
>>> os.listdir('/opt/awesome/source')
['awesome.txt']

这次我检查了源文件夹,以确保我创建的文件存在。它就在那里awesome.txt

现在,我们已将文件夹及其文件从源移动到目标,然后再移回。

评论

6赞 mac10688 5/4/2013
docs.python.org/2/library/shutil.html本文档显示您已为 shutil.move 方法切换了参数。
3赞 jmontross 5/8/2013
我使用反向目标和源来查看文件是否从源移动,然后又返回源。我能看出这是怎么回事。
0赞 Ludo Schmidt 3/30/2022
示例中的错误。src,dst 是反转的!
336赞 Jim Calfas 5/31/2013 #3

尽管 和 都会重命名文件,但最接近 Unix mv 命令的命令是 。不同之处在于,如果源和目标位于不同的磁盘上,则不起作用,而文件与磁盘无关。os.rename()shutil.move()shutil.move()os.rename()shutil.move()

评论

107赞 fmalina 1/22/2014
shutil.move()如果目标位于当前文件系统上,则使用。否则,请使用将源复制到目标,然后删除源。os.rename()shutil.move()shutil.copy2()
12赞 2rs2ts 4/2/2014
请注意,shutil.copy2() 无法复制所有文件元数据,因此,如果发生这种情况,就像做然后,我收集。cp -prm
11赞 Dana 5/30/2014
请注意:如果目标已经存在,则 Python 2.7.3 中的 shutil.move 会失败。因此,如果可能的话,要么捕获错误,要么手动删除文件/目录,然后进行移动。
17赞 Javier Palacios 10/17/2016 #4

公认的答案不是正确的,因为问题不在于将文件重命名为文件,而在于将许多文件移动到一个目录中。 将完成这项工作,但为此目的毫无用处(如注释中所述),因为目标必须具有显式文件名。shutil.moveos.rename

评论

0赞 Jacques Mathieu 3/16/2019
并非毫无用处,只是需要更多的工作才能让它移动多个文件。您可以使用 获取文件名,也可以使用 获取文件目录。此外,OP 并没有很清楚他是否想移动多个文件。他在问题中提到只移动一个文件,但他的示例代码暗示移动多个文件。os.path.basename(my_file_path)os.path.dirname(my_file_path)
30赞 Peter Vlaar 11/13/2016 #5

这是我目前使用的:

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)

您还可以将其转换为一个函数,该函数接受源目录和目标目录,如果目标文件夹不存在,则创建目标文件夹,并移动文件。还允许过滤 src 文件,例如,如果您只想移动图像,则使用 模式 ,默认情况下,它会移动目录中的所有内容'*.jpg'

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

评论

3赞 iggy12345 3/21/2019
您可以使用 fnmatch.filter() 轻松地将其转换为过滤移动,请参阅我的编辑。此外,最好使用字符串串联来避免跨平台问题os.path.join(parent_path, filename)
-1赞 Ned Slark 5/7/2018 #6
  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 

不同的磁盘,例如 C: --> D:

评论

0赞 jusopi 8/22/2018
如果您使用的是 Python3.#,则可以使用新的 f-string intrerpolation: 但鉴于您的字符串中没有静态文本,这可能会需要更多的工作。不过,我一直在努力养成使用 f 字符串的习惯。f"{new_path}{f}"
1赞 Matthew 12/10/2019
你的意思是 file 而不是 f?
1赞 Bill 6/16/2018 #7

根据此处描述的答案,使用是另一种选择。subprocess

像这样的东西:

subprocess.call("mv %s %s" % (source_files, destination_folder), shell=True)

我很想知道这种方法与.由于就我而言,我已经出于其他原因使用并且它似乎有效,因此我倾向于坚持下去。shutilsubprocess

这取决于运行脚本的 shell。该命令适用于大多数 Linux shell(bash、sh 等),但也适用于 Windows 上的 Git Bash 等终端。对于其他终端,您必须更改为备用命令。mvmv

评论

8赞 Joshua Schlichting 2/18/2020
我相信这将取决于系统。我没有看到在 Windows 操作系统上成功使用。mv
1赞 LightCC 10/21/2021
@JoshuaSchlichting 它比平台类型更依赖于 shell。例如,在 Windows 上,这在 Git Bash 终端中可以正常工作,但不能使用 Cmd。
0赞 Joshua Schlichting 10/22/2021
@LightCC 好渔获!谢谢!
0赞 LightCC 10/22/2021
我在最后一段中用正确的信息更新了答案,而不是一个问题,如果它取决于系统。
0赞 alper 9/12/2018 #8

这是解决方案,它不支持使用 。shellmv

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)
130赞 MoonFruit 10/12/2018 #9

在 Python 3.4 之后,您还可以使用 的类来移动文件。pathlibPath

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

评论

1赞 Amar 8/21/2020
我最近以 --> 的形式使用它来移动所有 *。LNK(快捷方式)文件复制到 DUMP 目录。像魅力一样工作!:DPath("path/to/current/file.foo").rename("path/to/new/destination/for/".joinpath(Path.name))
10赞 capooti 9/23/2020
这工作得很好,但如果你想将文件从一台设备移动到另一台设备,它将失败(无效的跨设备链接)
1赞 MoonFruit 4/16/2021
@Amar也许这样更好。Path("path/to/current/file.foo").rename(Path("path/to/new/destination/for") / Path.name))
2赞 Muhammedogz 4/20/2021 #10

也可以使用方法。subprocess.run()

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.

这在 Linux 上工作时可以正常工作。Windows 可能会给出错误,因为没有 mv 命令。

评论

1赞 Pranav Gupta 6/5/2021
当 python 有 API 时,为什么要调用外部进程?
4赞 Diego 7/21/2022 #11

既然你不在乎返回值,你可以做

import os
os.system("mv src/* dest/")