user2723965
user2723965

Reputation: 21

how to use os.listdir sorted by first directorys and then files in python?

I use os.listdir() and This code can traverse system directory structure, then generate a json file to django front-end of easyui call display tree UI:

def CreateDirTree(path,file_json):
    global id_num
    id_num=0
    def createDict(path):
            global id_num
            tree_list=[]
            pathList = os.listdir(path)
            for i,item in enumerate(pathList):
                    id_num+=1
                    children_map={}
                    children_map['id']=id_num
                    children_map['text']=item
                    if os.path.isdir(os.path.join(path,item)):
                            path = os.path.join(path,item)
                            print "directory:",path
                            tmp_listdir=os.listdir(path)
                            if  len(tmp_listdir) != 0:
                                    children_map['state']='closed'
                                    children_map['children'] = createDict(path)
                            tree_list.append(children_map)
                            path = '\\'.join(path.split('\\')[:-1])
                    else:
                        tree_list.append(children_map)
                        print children_map
            return tree_list

    tree_list=createDict(path)
    fjson = json.dumps(tree_list,ensure_ascii=False,sort_keys=False)
    with open(file_json,'w') as lf:
            lf.write(fjson)
    ##end
CreateDirTree("D:\\all_source\\somesite","123.json")

run and result is:

directory: D:\all_source\somesite\a

file is: b.txt

file is: oo.txt

file is: a.txt

directory: D:\all_source\somesite\b

file is: 123.txt

file is: b.txt
directory: D:\all_source\somesite\c

file is: yyt.txt

directory: D:\all_source\somesite\c\z

file is: c.txt

file is: e.txt

But I want to effect is:

directory: D:\all_source\somesite\a

a subdir files: 123.txt

a subdir files: abc.txt

directory: D:\all_source\somesite\b

directory: D:\all_source\somesite\c

directory: D:\all_source\somesite\c\z

file is: a.txt

file is: b.txt

file is: c.txt

file is: e.txt

first sorted by directory then sorted by files, How to do? please help me,thanks!

Upvotes: 1

Views: 2427

Answers (2)

BlackJack
BlackJack

Reputation: 4679

Here is a function to create the structure without a global variable and without calling os.listdir() twice for each directory:

import os
from itertools import count


def create_dir_tree(path):
    ids = count(0)
    def recurse(path):
        names = list()
        for name in os.listdir(path):
            full_name = os.path.join(path, name)
            names.append((os.path.isdir(full_name), name, full_name))
        names.sort(key=lambda n: (not n[0], n[1]))
        result = list()
        for is_dir, name, full_name in names:
            item = {'id': next(ids), 'text': name}
            if is_dir:
                children = recurse(full_name)
                if children:
                    item['state'] = 'closed'
                    item['children'] = children
            result.append(item)
        return result
    return recurse(path)

Like the original code one can't tell if an entry is a filename or an empty directory from the created data structure.

Upvotes: 2

ODiogoSilva
ODiogoSilva

Reputation: 2414

Create a list for directories and another for files and iterate over their concatenation. Adjusting from your code:

(...)
# List of directories only
dirlist = [x for x in os.listdir(path) if os.path.isdir(os.path.join(path, x))]
# List of files only
filelist = [x for x in os.listdir(path) if not os.path.isdir(os.path.join(path, x))]
for i,item in enumerate(dir_list + filelist):
(...)

This will start with directories and their subdirectories, and then move to the files

Upvotes: 4

Related Questions