简体   繁体   中英

how do i list existing files in a directory and subdirectories using recursion?

I am wondering if it's possible to put all files into a list even if they are present in different subdirectories without using os.walk

The function i have written does the job, but i don't want the files to be displayed in nested lists. I need them to be in a single list.

import os

def cerca(dir1): 
    
    lista1 = [] 
    for fname in os.listdir(dir1): 
        path = os.path.join(dir1,fname)
        if fname.startswith('.') : continue 
        if os.path.isfile(path): 
            lista1.append(fname)
    return lista1

def directory(dir1): 
    
    lista2 = cerca(dir1) 
    for fname in os.listdir(dir1): 
        path = os.path.join(dir1,fname) 
        if os.path.isdir(path): 
            ret = directory(path)
            lista2.append(ret)  
    return lista2 


output = [['looney-tunes.txt', [[['minnie.txt']]]], ['minnie.txt', ['looney-tunes.txt']],[['minnie.txt'], [['looney-tunes.txt']]]]

The output should instead be:

['looney-tunes.txt','minnie.txt','minnie.txt','looney-tunes.txt','minnie.txt','looney-tunes.txt']

Any help will be appreciated

Currently, you're only using the list.append method, which is why you're getting nested lists. You don't need to flatten the list if you make use of the list.extend method:

def walk(root):
    files = []
    for e in os.listdir(root):
        path = os.path.join(root, e)
        print(path)
        if os.path.isfile(path):
            files.append(e)
        else:
            files.extend(walk(path))

    return files

And then call the function like so:

root = "path-to-directory"
files = walk(root)

Firstly, we need to initialize an empty list, files so that we can keep track of the files that have already been iterated over. Now we just have to list the files using os.listdir and do a simple check if it's a file or a directory.

If it's a file, list.append does the trick.

If it's a directory, we need to use list.extend because if you append a list to a list, you're just going to get nested lists, like so:

files = ["top_file.txt", ["nested_file_0.txt", "nested_file_1.txt"]]

Using extend, we get something like this instead:

files = ["top_file.txt", "nested_file_0.txt", "nested_file_1.txt"]

I do not know why you do not want to use os.walk , as it is the most efficient way of recursively listing a directory's contents. If you really cannot use os.walk (for whatever reason), take no notice of this answer. But in case you might consider using os.walk , I made an exmaple of how,

import os

def walk(path):
    filelist = []
    for root, dirs, files in os.walk(path):
        filelist.append(list(filter(None, root.split(os.path.sep)))[-1]) # get the directory name we are currently in without the path and append it to the list
        filelist.extend(dirs + files) # extend the list  with the directories and files
    return filelist

To have a flat list without having to flatten it, you must use list.extend instead of list.append .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM