A Better Way To List Files In A Directory In Python

May - 2022

NOTE: This is still a draft in terms of the prose, but the code is tested and working. Still need to deal with hidden files though

Getting a list of files always feels like a pain. I wrote a JavaScript function a while ago to make it easier. It returns an array with details of the files.

I made a python version that does the same thing. The output look something like this:

[
  {
    'extension': 'txt',
    'full_path': '/Users/alan/list-dir-via-walk/samples/3/a.txt',
    'name_with_extension': 'a.txt',
    'name_without_extension': 'a',
    'root_dir': '/Users/alan/list-dir-via-walk/samples/3',
    'sub_dir': ''
  },
 {
    'extension': 'txt',
    'full_path': '/Users/alan/list-dir-via-walk/samples/3/3_lower_1/b.txt',
    'name_with_extension': 'b.txt',
    'name_without_extension': 'b',
    'root_dir': '/Users/alan/list-dir-via-walk/samples/3',
    'sub_dir': '3_lower_1'
  },
  {
    'extension': 'txt',
    'full_path': '/Users/alan/list-dir-via-walk/samples/3/3_lower_1/3_lower_2/c.txt',
    'name_with_extension': 'c.txt',
    'name_without_extension': 'c',
    'root_dir': '/Users/alan/list-dir-via-walk/samples/3',
    'sub_dir': '3_lower_1/3_lower_2'
  }
]

That makes it easy to get to individual files by name or path, with or without extension.

Here's the code

#!/usr/bin/env python3

import os
import glob

def listDir(*, root_dir, sub_dir=''):
    return_value = []
    root_dir_full = os.path.realpath(os.path.join(root_dir))
    dir_to_process = os.path.join(root_dir_full, sub_dir)

    file_list = [
        file for file in glob.glob(
            f"{dir_to_process}/*"
        )
        if os.path.isfile(file)
    ]

    for file in file_list:
        name_with_extension = os.path.basename(file)
        name_without_extension = os.path.splitext(name_with_extension)[0]
        extension = os.path.splitext(name_with_extension)[1].replace('.', '')

        return_value.append(
            {
                "root_dir": root_dir_full,
                "sub_dir": sub_dir,
                "name_with_extension": name_with_extension,
                "name_without_extension": name_without_extension,
                "extension": extension,
                "full_path": file
            }
        )


    sub_dir_list = [
        directory for directory in glob.glob(
            f"{dir_to_process}/*"
        )
        if os.path.isdir(directory)
    ]

    for sub_dir_full_path in sub_dir_list:
        base_sub_dir = sub_dir_full_path.replace(f'{root_dir_full}/', '')
        tmp_list = listDir(root_dir=root_dir_full, sub_dir=base_sub_dir)
        for item in tmp_list:
            return_value.append(item)


    return return_value