Python 重新排列嵌套目录
我有一个文件夹系统,结构如下:Python 重新排列嵌套目录,python,directory,shutil,python-os,Python,Directory,Shutil,Python Os,我有一个文件夹系统,结构如下: folderA - folder1 - file1A.txt - folder2 - file2A.txt - folder3 - file3A.txt folderB - folder1 - file1B.txt - folder2 - file2B.txt - folder3 - file3B.txt 我希望将信件文件夹上方的编号文件夹更改为: folder1 - folderA - file1A.txt - fol
folderA
- folder1
- file1A.txt
- folder2
- file2A.txt
- folder3
- file3A.txt
folderB
- folder1
- file1B.txt
- folder2
- file2B.txt
- folder3
- file3B.txt
我希望将信件文件夹上方的编号文件夹更改为:
folder1
- folderA
- file1A.txt
- folderB
- file1B.txt
folder2
- folderA
- file2A.txt
- folderB
- file2B.txt
folder3
- folderA
- file3A.txt
- folderB
- file3B.txt
下面是一段代码,用于构造初始目录结构的MWE:
import os
import shutil
import string
root_dir = os.getcwd()
os.chdir('/home/alletro/Tc-97/tools')
os.makedirs('master', exist_ok=True)
os.chdir('master')
master_dir = os.getcwd()
top_tier = [f'folder{i}' for i in range(1,4)]
second_tier = [f'folder{i}' for i in list(string.ascii_uppercase)[:4]]
for folder in top_tier:
os.chdir(master_dir)
os.makedirs(folder, exist_ok=True)
os.chdir(folder)
fold_dir = os.getcwd()
for sub_folder in second_tier:
os.chdir(fold_dir)
os.makedirs(sub_folder, exist_ok=True)
os.chdir(sub_folder)
os.mknod("newfile.txt")
os.chdir(root_dir)
import os, shutil, collections
#generator function that finds all file paths in the target directory
def get_files(d = os.getcwd(), p = None):
for i in os.listdir(d):
if os.path.isdir(_d:=os.path.join(d, i)):
yield from get_files(d = _d, p = ([] if p is None else p)+[i])
else:
yield ([] if p is None else p)+[i]
#group all reversed file paths from the function above on the leading dir name
def new_structure(d, p = []):
_dir = collections.defaultdict(list)
for a, b, c in d:
if not a:
shutil.copyfile(c, os.path.join(os.getcwd(), *p, b))
else:
_dir[a[0]].append((a[1:], b, c))
for a, b in _dir.items():
os.mkdir(os.path.join(os.getcwd(), *(_p:=p+[a])))
new_structure(b, p = _p)
r = [[a[::-1], b, os.path.join(*a, b)] for *a, b in get_files()]
new_structure(r)
#remove old structure
for (*_, a), _, _ in r:
if os.path.isdir(a):
shutil.rmtree(a, ignore_errors=False, onerror=None)
我找到了一个解决方案,可以为我提供目录树的字典:
def get_directory_structure(rootdir):
"""
Creates a nested dictionary that represents the folder structure of rootdir
"""
dir = {}
rootdir = rootdir.rstrip(os.sep)
start = rootdir.rfind(os.sep) + 1
for path, dirs, files in os.walk(rootdir):
folders = path[start:].split(os.sep)
subdir = dict.fromkeys(files)
parent = reduce(dict.get, folders[:-1], dir)
parent[folders[-1]] = subdir
return dir
然而,我正努力想知道该从何处着手。下面的内容对我很有用。分为四个部分:
import os
import glob
import shutil
all_files = [filename for filename in glob.iglob('**/*.txt', recursive=True)]
第2部分:使用文件名创建子文件夹列表
# Function that takes a filename and returns desired subfolder and file paths as tuple.
def get_full_path(file):
num = file[-6]
let = file[-5]
file_name = file.split('/')[-1]
subfolders = f'folder{num}/folder{let}/'
file_path = f'folder{num}/folder{let}/{file_name}'
return subfolders, file_path
# Call the function on each file to get all subfolders and file paths.
subfolders = []
full_paths = []
for file in all_files:
subfolder, full_path = get_full_path(file)
subfolders.append(subfolder), full_paths.append(full_path)
old_folders = [x for x in os.listdir() if x[-1] in ['A', 'B', 'C']]
for folder in old_folders:
shutil.rmtree(folder, ignore_errors=False, onerror=None)
第3部分:创建所有子文件夹,将所有文件移动到其中
for i in range(len(all_files)):
os.makedirs(subfolders[i])
os.rename(all_files[i], full_paths[i])
第4部分:删除原始文件夹和子文件夹
# Function that takes a filename and returns desired subfolder and file paths as tuple.
def get_full_path(file):
num = file[-6]
let = file[-5]
file_name = file.split('/')[-1]
subfolders = f'folder{num}/folder{let}/'
file_path = f'folder{num}/folder{let}/{file_name}'
return subfolders, file_path
# Call the function on each file to get all subfolders and file paths.
subfolders = []
full_paths = []
for file in all_files:
subfolder, full_path = get_full_path(file)
subfolders.append(subfolder), full_paths.append(full_path)
old_folders = [x for x in os.listdir() if x[-1] in ['A', 'B', 'C']]
for folder in old_folders:
shutil.rmtree(folder, ignore_errors=False, onerror=None)
如果文件夹“C”之外还有文件夹,则需要展开第4部分中['A'、'B'、'C']中的列表。否则,这应该任意缩放
让我知道如果你有任何问题,祝你好运与项目的其余部分 这里有一个不采用特定文件夹名称的解决方案:
从pathlib导入路径
def开关_部件(路径):
一、二、三、四=路径部分
返回路径(一、三、二、四)
#生成新路径
files=Path('master').glob('***.txt'))
重新排列=[在文件中为f切换_部分(f)]
#创建新文件夹并移动文件
对于zip中的新旧文件(文件,重新排列):
new.parent.mkdir(parents=True,exist\u ok=True)
旧。重命名(新)
#清理旧文件夹
对于旧in文件:
old.parent.rmdir()
尝试:
old.parent.parent.rmdir()文件
除操作错误外:
pass#最终将被删除
您可以首先获取文件的所有路径,然后使用递归创建新结构:
import os
import shutil
import string
root_dir = os.getcwd()
os.chdir('/home/alletro/Tc-97/tools')
os.makedirs('master', exist_ok=True)
os.chdir('master')
master_dir = os.getcwd()
top_tier = [f'folder{i}' for i in range(1,4)]
second_tier = [f'folder{i}' for i in list(string.ascii_uppercase)[:4]]
for folder in top_tier:
os.chdir(master_dir)
os.makedirs(folder, exist_ok=True)
os.chdir(folder)
fold_dir = os.getcwd()
for sub_folder in second_tier:
os.chdir(fold_dir)
os.makedirs(sub_folder, exist_ok=True)
os.chdir(sub_folder)
os.mknod("newfile.txt")
os.chdir(root_dir)
import os, shutil, collections
#generator function that finds all file paths in the target directory
def get_files(d = os.getcwd(), p = None):
for i in os.listdir(d):
if os.path.isdir(_d:=os.path.join(d, i)):
yield from get_files(d = _d, p = ([] if p is None else p)+[i])
else:
yield ([] if p is None else p)+[i]
#group all reversed file paths from the function above on the leading dir name
def new_structure(d, p = []):
_dir = collections.defaultdict(list)
for a, b, c in d:
if not a:
shutil.copyfile(c, os.path.join(os.getcwd(), *p, b))
else:
_dir[a[0]].append((a[1:], b, c))
for a, b in _dir.items():
os.mkdir(os.path.join(os.getcwd(), *(_p:=p+[a])))
new_structure(b, p = _p)
r = [[a[::-1], b, os.path.join(*a, b)] for *a, b in get_files()]
new_structure(r)
#remove old structure
for (*_, a), _, _ in r:
if os.path.isdir(a):
shutil.rmtree(a, ignore_errors=False, onerror=None)
此解决方案可用于任何深度的目录以及完全任意的目录和文件名。@Allentro为您完成了此工作吗?如果你还需要什么,请告诉我。谢谢,祝你好运!当旧路径和重新排列的路径不是不同的集合时,可能会出现一些问题(请尝试使用../folderX/folderX/…
),但我喜欢这个想法(+1)@VPfB很好。这种风险似乎是增加灵活性的代价。