How to iterate through more than two 'levels' of subfolders in python?

63 views Asked by At

I want to iterate through a directory with several 'levels' of subfolders (please excuse me if I use the wrong term for it), see the following list as an example:

$ tree folder/
folder/
├── lever1_1
│   └── level2_1
│       └── level3_1
│           ├── file1.txt
│           └── file2.txt
└── lever1_2
    └── level2_1
        └── level3_1

6 directories, 2 files

I want to check if there are .txt-files in the directory and if yes, I would like to modify the directory they are in (i.e. level3_1 in this example). This means it would be causing duplicates if I did something like

for dirs, files in os.walk("/home/user/folder"):
    for file in files:
        if file.endswith(".txt"):
            # do something to the directory they are in

because there are several .txt-files in level3_1, but I only want to modify it once.

If I use for dirs, files in os.walk("/home/user/folder") I get the error "too many values to unpack (expected 2)" , which I understand, but I cannot work with a fixed set of directory levels as they can vary throughout the use cases.

Does anybody have an idea how to do this in an efficient way?

Kind regards

2

There are 2 answers

0
ChocoNao On BEST ANSWER

You need to adjust how you're iterating through the results. Since os.walk() returns a tuple of (dirpath, dirnames, filenames) for each directory , you need to unpack this tuple accordingly:

import os

root_folder = "./folder"

if __name__ == '__main__':
    for dirpath, dirnames, filenames in os.walk(root_folder):
        if any(file.endswith(".txt") for file in filenames):
            # Do something to the directory
            print(f'Found {filenames[0]} file in: {dirpath}')
0
Gilles Quénot On

Given this files/directories structure:

$ tree folder/
folder/
├── lever1_1
│   └── level2_1
│       └── level3_1
│           ├── file1.txt
│           └── file2.txt
└── lever1_2
    └── level2_1
        └── level3_1

6 directories, 2 files

What you need:

import os

if __name__ == '__main__':
    for root, dirs, files in os.walk("./folder"):
        for file in files:
            if file.endswith(".txt"):
                print(file)

To loop over os.walk, you need to add an argument like root (like I does here), because it returns 3 elements.

See https://docs.python.org/3/library/os.html