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
Python moving files and directories from one folder to another
提问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.listdir
just 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 listdir
is 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.move
say, os.rename
or shutil.copy2
will 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.rename
will 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.move
source* and using os.replace
instead, as the rename
docs 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 spam
to a target eggs/spam
, and eggs/spam
already 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 mv
on Unix and move
on Windows do, which is what shutil
is trying to simulate.
这应该不足为奇,因为它mv
在 Unix 和move
Windows上完全相同,这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 True
and 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))