zester
zester

Reputation: 175

How to store absolute paths and display them as a directory structure in python?

I am given a list of list of absolute directory paths in a list as:-

 [ ['19.2.000/'],['19.2.000/data/'],
 ['19.2.000/data/datainstaller.zip'], ['19.2.000/data/rs_details'],
 ['19.2.000/rem/'],
 ['19.2.000/rem/remapp.zip'], ['19.2.000/rem/rs_details'],
 ['19.2.000/res/'], ['19.2.000/res/resapp.zip'], ['19.2.000/rms/'],
 ['19.2.000/rms/BdiEdge.zip'], ['19.2.001/'],
 ['19.2.001/dataconversion/'],
 ['19.2.001/dataconversion/dataconversioninstaller.zip'],
 ['19.2.001/dataconversion/rs_details'] ]

And I want to display the directory structure as:-

|--19.2.000
|   |--data
|   |   |--datainstaller.zip
|   |   |--rs_details
|   |--rem
|   |   |--remapp.zip
|   |   |--rs_details
|   |--res
|   |   |--resapp.zip
|   |--rms
|   |   |--BdiEdge.zip
|--19.2.001
|   |--dataconversion
|   |   |--dataconversioninstaller.zip
|   |   |--rs_details

I tried to do it with nested for loops (by storing each level in a different lists) but with increasing levels of directory, it becomes redundant and slow. Any other way to optimally display it?

Upvotes: 2

Views: 150

Answers (1)

srattigan
srattigan

Reputation: 664

I'd start by sorting the lists- then they are in the order you want at least. This was extrapolated out to use vars for the indents based on num '/' and what index of the split on '/' gets used.

This problem caught my interest to be honest, so here is a version that should work with any dir structure you supply as a list, even if some of the sub-folders are not listed.

def make_fldr(arr):
    print("-- Processing Pass 1 --")
    processed = []
    path_repr = ''
    sub_dir = '|  '
    for path in arr:
        dirs = path[0].split("/")
        num_slash = path[0].count('/')
        sep = '/'
        for i in range(num_slash):
            rep = sep.join(dirs[:i+1])
            if [rep+'/'] not in arr:
                arr.append([rep+'/'])
    [processed.append(x) for x in arr if x not in processed] 
    print("-- Building structure: Pass 2 --")
    processed.sort()
    print("Processed List is sorted")
    for path in processed:
        num_slash = path[0].count('/')
        if num_slash == 1:
            piece = path[0].split("/")
            if piece[1] == '':
                path_repr += f'|--{piece[0]}\n'
            else:
                path_repr += f'{sub_dir}|--{piece[1]}\n'
        else:
            if path[0].split("/")[-1] == '':
                path_repr += f'{sub_dir * (num_slash-1)}|--{path[0].split("/")[-2]}\n'
            else:
                path_repr += f'{sub_dir * num_slash}|--{path[0].split("/")[-1]}\n'
    return path_repr


structure = make_fldr(data)
print(structure)

Given an expanded set

data = [
        ['19.2.000/'],
        ['19.2.000/resa/'],
        ['19.2.000/resa/resa19application.zip'],
        ['19.2.000/rms/'],
        ['19.2.000/rms/BdiEdgeAppJobAdminPak19.1.000ForRms19.1.000_eng_ga.zip'],
        ['19.2.001/'],
        ['19.2/'],
        ['19.2/rpm/'],
        ['19.2/rpm/release_details'],
        ['19.2/rpm/rpm19application.zip'],
        ['RESA/'],
        ['RESA/folder1/'],
        ['RESA/folder1/release_details'],
        ['RESA/folder1/resainstaller.zip'],
        ['RESA/release_details'],
        ['RESA/resainstaller.zip'],
        ['RMS/'],
        ['RMS/release_details'],
        ['RMS/rmsinstaller.zip'],
        ['RPM/'],
        ['RPM/release_details'],
        ['RPM/rpminstaller.zip']
        ]

the function above yields

Processed List is sorted
|--19.2.000
|  |--resa
|  |  |--resa19application.zip
|  |--rms
|  |  |--BdiEdgeAppJobAdminPak19.1.000ForRms19.1.000_eng_ga.zip
|--19.2.001
|--19.2
|  |--rpm
|  |  |--release_details
|  |  |--rpm19application.zip
|--RESA
|  |--folder1
|  |  |--release_details
|  |  |--resainstaller.zip
|  |--release_details
|  |--resainstaller.zip
|--RMS
|  |--release_details
|  |--rmsinstaller.zip
|--RPM
|  |--release_details
|  |--rpminstaller.zip

I tested with the complete file you shared- it seems to work ok. The reason the earlier version did not work was that I'd assumed all sub-dirs ended with a '/', but some did not. Once I tested with the complete set I could work out where the error was happening.

Upvotes: 2

Related Questions