Python 将文件和目录从一个文件夹移动到另一个文件夹

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27545454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 01:56:52  来源:igfitidea点击:

Python moving files and directories from one folder to another

python

提问by Richard

I would like to move in python files and directories in one directory to another directory with overwrite ability.

我想将一个目录中的 python 文件和目录移动到具有覆盖能力的另一个目录。

I started with the following code:

我从以下代码开始:

        #moving files from progs
        path = tempfolder + 'progs/'
        for dirs,files in os.listdir(path):
                 for f in files:
                        shutil.move(os.path.join(path, f) , os.path.join(compteurfolder, f))

So for the moment, I only try to move the files and I get the following errors:

所以目前,我只尝试移动文件,但出现以下错误:

    for dirs,files in os.listdir(path):
ValueError: too many values to unpack

I guess this is because I have dirs and files but then how will I move directories too? And how to make sure it can overwrite the files in the other folder?

我想这是因为我有目录和文件,但是我将如何移动目录呢?以及如何确保它可以覆盖另一个文件夹中的文件?

Hope you can help.

希望你能帮忙。

采纳答案by abarnert

The reason this fails:

失败的原因:

for dirs,files in os.listdir(path):

… is that os.listdirjust returns a list of filenames. So, each element is a string, and you're trying to unpack that string into two variables. Compare this:

...os.listdir只是返回一个文件名列表。因此,每个元素都是一个字符串,您正在尝试将该字符串解包为两个变量。比较一下:

a, b = (1, 2, 3, 4, 5, 6, 7, 8)
for a, b in [(1, 2, 3, 4, 5, 6, 7, 8), (9, 10)]
dirs, files = "spam.txt"
for dirs, files in ["spam.txt", "eggs.dat"]

It's the exact same error in every case—you can't fit 8 things into 2 variables.

在每种情况下都是完全相同的错误——你不能将 8 个东西放入 2 个变量中。

Meanwhile, if listdiris just returning filenames, how do you know ones are the names of regular files, are which are the names of directories? You have to ask—e.g., by using isdir.

同时,如果listdir只是返回文件名,你怎么知道那些是常规文件的名称,哪些是目录的名称?您必须询问——例如,通过使用isdir.

So:

所以:

for filename in os.listdir(path):
    if os.path.isdir(filename):
        # do directory stuff
    else:
        # do regular file stuff

(But note that this can still be confusing if you have symlinks…)

(但请注意,如果您有符号链接,这仍然会令人困惑……)



Meanwhile, what does "do regular file stuff" mean?

同时,“做常规文件的东西”是什么意思?

Well, assuming you don't have a directory (or a symlink to a directory) with the same name as the file you're trying to move there, as the docs for shutil.movesay, os.renameor shutil.copy2will be used. If you're not on Windows, this is perfect—if you have permission to overwrite the target you will, otherwise you'll get a permissions error. But if you areon Windows, os.renamewill fail if the target already exists.

好吧,假设您没有与您尝试移动到那里的文件同名的目录(或目录的符号链接),正如文档shutil.move所说,os.rename或者shutil.copy2将被使用。如果你不是在 Windows 上,这是完美的——如果你有权限覆盖目标,你会,否则你会得到权限错误。但是,如果你在Windows上,os.rename会如果目标已经存在失败。

If you're on 3.3 or later, you can solve this by copying the shutil.movesource* and using os.replaceinstead, as the renamedocs imply. Otherwise, you will have to delete the target before renaming the source.

如果您使用的是 3.3 或更高版本,则可以通过复制shutil.move* 并使用os.replace来解决此问题,正如rename文档所暗示的那样。否则,您必须在重命名源之前删除目标。

* Some stdlib modules—including shutil—are meant to serve as sample code as well as usable helpers. In those cases, at the top of the module's docs, there will be a Source code:link.

* 一些 stdlib 模块(包括shutil)旨在用作示例代码以及可用的帮助程序。在这些情况下,在模块文档的顶部,会有一个Source code:链接。



And what about "do directory stuff"? Well, if you move a directory spamto a target eggs/spam, and eggs/spamalready exists as a directory, you're going to end up moving to eggs/spam/spam.

那么“做目录的东西”呢?好吧,如果您将目录移动spam到 target eggs/spam,并且eggs/spam已经作为目录存在,那么您最终将移动到eggs/spam/spam.

This shouldn't be surprising, as it's exactly the same thing mvon Unix and moveon Windows do, which is what shutilis trying to simulate.

这应该不足为奇,因为它mv在 Unix 和moveWindows上完全相同,这shutil就是试图模拟的。

So, what you need to do here is delete the target (this time using shutil.rmtree) before moving the source.

因此,您在这里需要做的是shutil.rmtree在移动源之前删除目标(这次使用)。



Which means the simplest thing to do may be to not distinguish files and directories, Windows and Unix, or anything else; just do this:

这意味着最简单的事情可能是不区分文件和目录、Windows 和 Unix 或其他任何东西;只需这样做:

for filename in os.listdir(path):
    target = os.path.join(compteurfolder, filename)
    try:
        shutil.rmtree(target)
    except NotADirectoryError:
        try:
            os.unlink(target)
        except FileNotFoundError:
            pass
    shutil.move(os.path.join(path, filename), target)

回答by Khamidulla

This because os.listdir(path) return array according documentation here. So you should modify you code as following for moving files and directories.

这是因为 os.listdir(path) 根据此处的文档返回数组。所以你应该修改你的代码如下来移动文件和目录。

    #moving files from progs
    path = tempfolder + 'progs/'
    for item_path in os.listdir(path):
        shutil.move(os.path.join(path, item_path) , os.path.join(compteurfolder, item_path)

回答by navyad

>>> import os
>>> import shutil

>>> for node in os.listdir(path):
...      if not os.path.isdir(node):
...          shutil.move(os.path.join(path, node) , os.path.join(compteurfolder, node))

回答by FiendishDesigns

(Python 3.6) From a previous answer (can't add comment)

(Python 3.6)来自上一个答案(无法添加评论)

I think that the line

我认为这条线

if not os.path.isdir(node):

Should read

应该读

if not os.path.isdir(os.path.join(source, node))

Otherwise it will always return Trueand move the sub folders as well.

否则它总是会返回True并移动子文件夹。

>>> import os
>>> import shutil

>>> for node in os.listdir(path):
...      if not os.path.isdir(os.path.join(path, node)):
...          shutil.move(os.path.join(path, node) , os.path.join(compteurfolder, node))