0

I am trying to build following structure using Python

├───Baseframework
│   ├───0_src
│   │   ├───Appfun
│   │   │   ├───Cpugeneric
│   │   │   ├───i5t
│   │   │   ├───Tricore
│   │   │   └───vpprint
│   │   └───Base
│   │       ├───gnfru
│   │       ├───ills
│   │       └───service
│   ├───1_toolbar
│   │   └───0_build
│   │       ├───0_utilites
│   │       ├───1_config
│   │       └───9_make
│   └───2_out
│       ├───tasking
│       └───tricore

Here's my code

import os
import argparse


base_path = "c:/usr"

# level_zero = "Baseframework"
levels = {"Baseframework":{"0_src":{"Appfun":["Cpugeneric", "i5t", "Tricore", "vpprint"], "Base":["ills","gnfru","service"]},
                           "1_toolbar":{"0_build":["0_utilities", "1_config", "9_make"]},
                           "2_out": ["ist_tasking","tricore_gyne"]}}

def iterdict(d, bd, flag = 1):

    for k,v in d.items():
        if isinstance(v, dict):
            print(flag)
            if flag==1:
                bd = os.path.join(bd,k)
                print(bd)
            else:
                bd = os.path.join(os.path.abspath(bd+"/.."),k)
                print(bd)

            if not os.path.exists(bd):
                    os.mkdir(bd)
            iterdict(v, bd)
        elif isinstance(v, list):
            bd1 = os.path.join(bd, k)
            if not os.path.exists(bd1):
                os.mkdir(bd1)
            for i in v:
                os.mkdir(os.path.join(bd1, i))
            flag = 0

iterdict(levels, base_path)

The above code creates a structure:

├───Baseframework
│   └───0_src
│       ├───1_toolbar
│       │   ├───0_build
│       │   │   ├───0_utilities
│       │   │   ├───1_config
│       │   │   └───9_make
│       │   └───2_out
│       │       ├───ist_tasking
│       │       └───tricore_gyne
│       ├───Appfun
│       │   ├───Cpugeneric
│       │   ├───i5t
│       │   ├───Tricore
│       │   └───vpprint
│       └───Base
│           ├───gnfru
│           ├───ills
│           └───service

Logic and Explanation:

Whenever I encounter list, I set flag=False so that I can go 1 step back for next iteration when value is dict.

But unfortunately value of flag variable is not changing. I can't get my head around it why value is not changing it is always 1.

Note: Kindly ignore if there's mismatch between folder name in Tree structure and code. It's just an example.

3 Answers 3

1

whenever you are calling function , then you need to pass the new path to the function not the base path

import os
import argparse


base_path = r"<base directory path>"

# level_zero = "Baseframework"
levels = {"Baseframework":{"0_src":{"Appfun":["Cpugeneric", "i5t", "Tricore", "vpprint"], "Base":["ills","gnfru","service"]},
                           "1_toolbar":{"0_build":["0_utilities", "1_config", "9_make"]},
                           "2_out": ["ist_tasking","tricore_gyne"]}}

def func(data, path):
    new_path = ''
    if isinstance(data, dict):
        for k, v in data.items():
            new_path = os.path.join(path, k)
            os.mkdir(new_path)
            func(v, new_path)
    elif isinstance(data, list):
        for _dir in data:
            new_path = os.path.join(path, _dir)
            os.mkdir(new_path)
    else:
        exit(0)

func(levels, base_path)
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, it worked as expected. I guess using for loop before if was causing the issue.
1

I would suggest using pathlib for this for anything python 3.6+

from pathlib import Path

base_path = Path("c:/usr")

levels = {"Baseframework":{"0_src":{"Appfun":["Cpugeneric", "i5t", "Tricore", "vpprint"], "Base":["ills","gnfru","service"]},
                           "1_toolbar":{"0_build":["0_utilities", "1_config", "9_make"]},
                           "2_out": ["ist_tasking","tricore_gyne"]}}

def iterdict(d:dict, bd: Path):
    """recursively creates directory structure from dictionaries"""
    for k,v in d.items():
        if isinstance(v, dict):
            bd.pathjoin(k).mkdir(exist_ok=True)
            iterdict(v, bd.pathjoin(k))
        else:
            for file in v:
                bd.pathjoin(k).mkdir(exist_ok=True)


iterdict(levels, base_path)

2 Comments

throws an error AttributeError: 'str' object has no attribute 'joinpath'
oops backwards.
1

This is a version which allows list to contains other dicts:

import os

base_path = "c:/usr"

levels = {"Baseframework":{"0_src":{"Appfun":["Cpugeneric", "i5t", "Tricore", "vpprint"], "Base":["ills","gnfru","service"]},
                           "1_toolbar":{"0_build":["0_utilities", "1_config", "9_make"]},
                           "2_out": ["ist_tasking","tricore_gyne"]}}

def iterdict(levels, base_path):
    if  isinstance(levels, dict):
        for k, v in levels.items():
            iterdict(v, os.path.join(base_path, k))
    elif isinstance(levels, list):
        [iterdict(e, base_path) for e in levels]
    else:
        os.makedirs(os.path.join(base_path, levels), exist_ok=True)

iterdict(levels, base_path)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.