2

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

alex108
  • 387
  • 2
  • 11
  • 2
    Does this answer your question? [How to make a flat list out of list of lists?](https://stackoverflow.com/questions/952914/how-to-make-a-flat-list-out-of-list-of-lists) – Rocket Nikita Feb 10 '21 at 11:34
  • Does this answer your question? [Flatten an irregular list of lists](https://stackoverflow.com/questions/2158395/flatten-an-irregular-list-of-lists) – Tomerikoo Feb 10 '21 at 12:15
  • Nope it doesn't – alex108 Feb 10 '21 at 12:28

2 Answers2

2

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"]
gmdev
  • 2,725
  • 2
  • 13
  • 28
  • @alex108 no problem, enjoy! – gmdev Feb 10 '21 at 11:47
  • Hey, one important question. What would you add to the code if you wanted to search the files that are present at a given depth?. For example, if 3 depth is given, i should output only the files at depth 3. – alex108 Feb 10 '21 at 11:51
  • You should pass a `max_depth` and a `current_depth` parameter to the function so that the signature is now `walk(root, max_depth, current_depth=0)`. This is so that you can keep track of the depths as recursion continues. You should increment the depth like so: `files.extend(walk(path, 3, current_depth+1))`. You should then have an `if statement` to check whether or not `max_depth == current_depth`. – gmdev Feb 10 '21 at 20:35
0

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.

TheEagle
  • 5,808
  • 3
  • 11
  • 39