[英]How to move a directory in Python?
我需要將目錄從一個位置移動到同一文件系統上的另一個位置。 我知道像shutil.move()
這樣的解決方案,但是有問題的文件系統是 SD 卡(因此非常慢),並且有很多文件要移動,所以簡單地復制它們然后刪除原件不是可接受的。 Unix mv
命令可以將一個目錄從一個文件系統移動到同一個文件系統而無需復制任何文件——在 Python 中有沒有辦法做到這一點?
事實證明,答案是肯定的。 您可能知道,您可以使用os.rename(r'D:\path1\myfile.txt', r'D:\path2\myfile.txt')
移動文件(假設它不存在於目標位置) os.rename(r'D:\path1\myfile.txt', r'D:\path2\myfile.txt')
。 您可以對目錄執行相同的操作:
os.rename(r'D:\long\path\to\mydir', r'D:\mydir')
但是,當然,這只有在 D:\mydir 不存在的情況下才有效。 如果它確實存在,並且您想將已經存在的文件與您正在移動的文件合並,您需要變得更聰明一些。 這是一個片段,可以做你想做的事:
def movedir(src, dst):
try:
os.rename(src, dst)
return
except FileExistsError:
pass
for root, dirs, files in os.walk(src):
dest_root = os.path.join(dst, os.path.relpath(root, src))
done = []
for dir_ in dirs:
try:
os.rename(os.path.join(root, dir_), os.path.join(dest_root, dir_))
done.append(dir_)
except FileExistsError:
pass
for dir_ in done:
dirs.remove(dir_)
for file in files:
os.replace(os.path.join(root, file), os.path.join(dest_root, file))
for root, dirs, files in os.walk(src, topdown=False):
os.rmdir(root)
這是一個帶有注釋的版本,解釋了一切的作用:
def movedir(src, dst):
# if a directory of the same name does not exist in the destination, we can simply rename the directory
# to a different path, and it will be moved -- it will disappear from the source path and appear in the destination
# path instantaneously, without any files being copied.
try:
os.rename(src, dst)
return
except FileExistsError:
# if a directory of the same name already exists, we must merge them. This is what the algorithm below does.
pass
for root, dirs, files in os.walk(src):
dest_root = os.path.join(dst, os.path.relpath(root, src))
done = []
for dir_ in dirs:
try:
os.rename(os.path.join(root, dir_), os.path.join(dest_root, dir_))
done.append(dir_)
except FileExistsError:
pass
# tell os.walk() not to recurse into subdirectories we've already moved. see the documentation on os.walk()
# for why this works: https://docs.python.org/3/library/os.html#os.walk
# lists can't be modified during iteration, so we have to put all the items we want to remove from the list
# into a second list, and then remove them after the loop.
for dir_ in done:
dirs.remove(dir_)
# move files. os.replace() is a bit like os.rename() but if there's an existing file in the destination with
# the same name, it will be deleted and replaced with the source file without prompting the user. It doesn't
# work on directories, so we only use it for files.
# You may want to change this to os.rename() and surround it with a try/except FileExistsError if you
# want to prompt the user to overwrite files.
for file in files:
os.replace(os.path.join(root, file), os.path.join(dest_root, file))
# clean up after ourselves.
# Directories we were able to successfully move just by renaming them (directories that didn't exist in the
# destination already) have already disappeared from the source. Directories we had to merge are still there in
# the source, but their contents were moved. os.rmdir() will fail unless the directory is already empty.
for root, dirs, files in os.walk(src, topdown=False):
os.rmdir(root)
movedir(r'D:\long\path\to\mydir', r'D:\mydir')
請注意,以這種方式使用 os.rename() 僅在源路徑和目標路徑位於同一文件系統上時才有效(在 Windows 上,如果它們具有相同的驅動器號,則為真)。 如果它們在不同的驅動器號上(即一個在 C: 上,另一個在 D: 上)或者如果其中一個路徑包含重解析點(如果您不知道那是什么,請不要擔心) ,你可能永遠不會遇到),你將需要使用shutil.move()
,它復制文件然后從源中刪除它們——這就是 Windows 在驅動器之間移動文件時所做的,它大約需要很長的時間才能完成。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.