Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 重新排列嵌套目录_Python_Directory_Shutil_Python Os - Fatal编程技术网

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

然而,我正努力想知道该从何处着手。

下面的内容对我很有用。分为四个部分:

  • 获取所有文件路径的列表
  • 使用该列表创建所需子文件夹的列表
  • 创建子文件夹并将文件移动到其中
  • 删除旧的文件层次结构
  • 第1部分:获取文件路径列表

    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很好。这种风险似乎是增加灵活性的代价。