0

Suppose the following directory structure: -

|--apc
|   |--data
|   |   |--datainstaller.zip
|   |   |--rs_details
|   |   |   |--readme.txt
|   |--rem
|   |   |--15.0.x
|   |   |   |--15.0.1
|   |   |   |   |--dataconversion
|   |   |   |   |   |--details.txt
|   |   |   |--15.0.2
|   |   |   |   |--dataconversion
|   |   |   |   |   |--details.txt
|   |   |--alloc_details.txt
|   |--res
|   |   |--resapp.zip
|--REIM
|   |--dataconversion
|   |   |--dataconversioninstaller.zip
|   |   |--rs_details.txt
|   |--reim_bkp.zip
|   |--hotfix
|   |   |--mergedRC
|   |   |   |--alloc
|   |   |   |   |--p231.zip
|--testfile1.txt
|--testfile2.txt

is given as absolute paths (starting from the root directory and in a depth-first manner) in a python list as ( i.e., the paths are given as strings in a list) :-

['apc/','apc/data/', 'apc/data/datainstaller.zip', 'apc/data/rs_details/', 'apc/data/rs_details/readme.txt', 'apc/rem/', 'apc/rem/15.0.x/', 'apc/rem/15.0.x/15.0.1/', 'apc/rem/15.0.x/15.0.1/dataconversion/', 'apc/rem/15.0.x/15.0.1/dataconversion/details.txt', 'apc/rem/15.0.x/15.0.2/', 'apc/rem/15.0.x/15.0.2/dataconversion/', 'apc/rem/15.0.x/15.0.2/dataconversion/details.txt', 'apc/rem/alloc_details.txt', 'apc/res/', 'apc/res/resapp.zip', 'REIM/', 'REIM/dataconversion/', 'REIM/dataconversion/dataconversioninstaller.zip', 'REIM/dataconversion/rs_details.txt', 'REIM/reim_bkp.zip', 'REIM/hotfix/', 'REIM/hotfix/mergedRC/', 'REIM/hotfix/mergedRC/alloc', 'REIM/hotfix/mergedRC/alloc/p231.zip', 'testfile1.txt', 'testfile2.txt']

I want to create a nested dictionary to store this directory structure which would be something like this :-

  {
       'apc/': {

                'apc/data/':{
                             'apc/data/datainstaller.zip' : {}
                              'apc/data/rs_details/' : {
                                            'apc/data/rs_details/readme.txt' : {}
                                         }
                          
                'apc/rem/':{
                                'apc/rem/15.0.x' : {
                                                'apc/rem/15.0.x/15.0.1/': { 
                                                                             'apc/rem/15.0.x/15.0.1/dataconversion' : { 'apc/rem/15.0.x/15.0.1/dataconversion/details.txt' : {} }
                                         }
                                                'apc/rem/15.0.x/15.0.2/': { 
                                                                             'apc/rem/15.0.x/15.0.2/dataconversion' : { 'apc/rem/15.0.x/15.0.2/dataconversion/details.txt' : {} }
                                         }
                             }
                       }
             }
   }

I tried to do it iteratively as well as recursively too by using the parameter as number of / in the path and finding prefix in the lower level directory paths but it resulted in an inconsistent nested dictionary and I could not get the desired one as shown above.

Can anyone help me out with this?

[Edit: The path string of directories always end with a / whereas the path string of files do not]

5
  • Can you share your code, and the output from your code? Commented Mar 5, 2021 at 6:16
  • 1
    What's the point of your dict data structure? Part of the key is duplicated. Commented Mar 5, 2021 at 6:17
  • @AllanWind I will be using the dictionary to display the actual directory structure on frontend. Can you let me know where is the key duplicated? Commented Mar 5, 2021 at 6:20
  • For a given non-root node the prefix is repeated (for instance, 'apc/' is repeated in all the keys in your example). Why does the dict help you display the structure on the front-end? Commented Mar 5, 2021 at 6:27
  • I kept the entire prefix in the key for reference of this question but while displaying it on frontend only the directory/file name will be displayed and not the prefix. The dict helps me in displaying the structure on frontend because I would be displaying it as an accordion (i.e., a collapsable structure) and this will help me in displaying the sub directories easily. Please refer to this question Commented Mar 5, 2021 at 6:36

1 Answer 1

1

This would do it:

import os, json

directory_dict = {}

path_list = ['apc/','apc/data/', 'apc/data/datainstaller.zip', 'apc/data/rs_details/', 'apc/data/rs_details/readme.txt', 'apc/rem/', 'apc/rem/15.0.x/', 'apc/rem/15.0.x/15.0.1/', 'apc/rem/15.0.x/15.0.1/dataconversion/', 'apc/rem/15.0.x/15.0.1/dataconversion/details.txt', 'apc/rem/15.0.x/15.0.2/', 'apc/rem/15.0.x/15.0.2/dataconversion/', 'apc/rem/15.0.x/15.0.2/dataconversion/details.txt', 'apc/rem/alloc_details.txt', 'apc/res/', 'apc/res/resapp.zip', 'REIM/', 'REIM/dataconversion/', 'REIM/dataconversion/dataconversioninstaller.zip', 'REIM/dataconversion/rs_details.txt', 'REIM/reim_bkp.zip', 'REIM/hotfix/', 'REIM/hotfix/mergedRC/', 'REIM/hotfix/mergedRC/alloc', 'REIM/hotfix/mergedRC/alloc/p231.zip', 'testfile1.txt', 'testfile2.txt']

for item in path_list:
    path, filename = os.path.split(item)
    split_path = path.split('/')
    # directory_level is a pointer into the directory_dict
    directory_level = directory_dict
    # current_directory is a string to hold the path name as we build it up again from iterating the split_path list
    current_directory = ''

    for path_item in split_path:
        # build up the current_directory
        current_directory += path_item + '/'
        if current_directory not in directory_level:
            # insert new dictionary at this level
            directory_level[current_directory] = {}
        # set the directory_level pointer to new level
        directory_level = directory_level[current_directory]

    if filename:
        # add the whole item into the dictionary at this level
        directory_level[item] = {}

print(json.dumps(directory_dict, indent=4)) 

And the output:

{
    "apc/": {
        "apc/data/": {
            "apc/data/datainstaller.zip": {},
            "apc/data/rs_details/": {
                "apc/data/rs_details/readme.txt": {}
            }
        },
        "apc/rem/": {
            "apc/rem/15.0.x/": {
                "apc/rem/15.0.x/15.0.1/": {
                    "apc/rem/15.0.x/15.0.1/dataconversion/": {
                        "apc/rem/15.0.x/15.0.1/dataconversion/details.txt": {}
                    }
                },
                "apc/rem/15.0.x/15.0.2/": {
                    "apc/rem/15.0.x/15.0.2/dataconversion/": {
                        "apc/rem/15.0.x/15.0.2/dataconversion/details.txt": {}
                    }
                }
            },
            "apc/rem/alloc_details.txt": {}
        },
        "apc/res/": {
            "apc/res/resapp.zip": {}
        }
    },
    "REIM/": {
        "REIM/dataconversion/": {
            "REIM/dataconversion/dataconversioninstaller.zip": {},
            "REIM/dataconversion/rs_details.txt": {}
        },
        "REIM/reim_bkp.zip": {},
        "REIM/hotfix/": {
            "REIM/hotfix/mergedRC/": {
                "REIM/hotfix/mergedRC/alloc": {},
                "REIM/hotfix/mergedRC/alloc/": {
                    "REIM/hotfix/mergedRC/alloc/p231.zip": {}
                }
            }
        }
    },
    "/": {
        "testfile1.txt": {},
        "testfile2.txt": {}
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for pointing out. It was a typo for apc/rem/15.0.x/15.0.1/dataconversion and apc/rem/15.0.x/15.0.2/dataconversion . Both are directories and will end with a /. I have updated it in the question

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.