Tidy Desk Digital ยท Free guides

Listing a Folder's Files in Python

List a folder's files and sizes before checking a copy. The program visits subfolders and sorts the paths into a report you can read or use in another program.

You'll need Python 3, a plain-text editor and a command window. No extra packages are required.

1. Prepare a small folder

Use a practice folder that does not already contain Example. Save this as MakeFolder.py there:

from pathlib import Path


Folder = Path("Example")
Folder.mkdir()
(Folder / "Sub").mkdir()
(Folder / "Note.txt").write_bytes(b"abc")
(Folder / "Sub" / "Data.txt").write_bytes(b"xy")

Run:

python3 MakeFolder.py

Use your installation's Python 3 command if it is not named python3. It creates this layout:

Example/
    Note.txt
    Sub/
        Data.txt

Python writes exactly abc and xy as bytes, with no line endings. A byte is a small unit of stored data. This gives predictable sizes even if your editor normally adds line endings to text files.

If Example already exists, the setup stops at Folder.mkdir() before writing either file. Start in another practice folder rather than changing that safeguard or removing files you need. Save the listing program outside Example so it does not list itself.

2. Save the program

Save this as ListFolder.py:

import json as Json
import sys as Sys
from pathlib import Path


def ListFolder(FolderPath):
    Folder = Path(FolderPath)
    if Folder.is_symlink():
        raise ValueError("folder must not be a symbolic link")
    if not Folder.is_dir():
        raise ValueError("input must be a folder")
    Records = []
    SkippedLinks = []
    Pending = [Folder]
    Seen = 0
    while Pending:
        Current = Pending.pop()
        for Item in Current.iterdir():
            Seen += 1
            if Seen > 10000:
                raise ValueError("folder exceeds the 10000-entry limit")
            Relative = Item.relative_to(Folder).as_posix()
            if Item.is_symlink():
                SkippedLinks.append(Relative)
            elif Item.is_dir():
                Pending.append(Item)
            elif Item.is_file():
                Records.append({"Path": Relative, "Bytes": Item.stat().st_size})
            else:
                raise ValueError("folder contains an unsupported file type")
    Records.sort(key=lambda Record: Record["Path"])
    SkippedLinks.sort()
    return {"Files": Records, "SkippedLinks": SkippedLinks}


def Main():
    if len(Sys.argv) != 2:
        print("Usage: python3 ListFolder.py folder", file=Sys.stderr)
        return 2
    try:
        Report = ListFolder(Sys.argv[1])
    except (OSError, ValueError) as Problem:
        print(f"Listing stopped: {Problem}", file=Sys.stderr)
        return 2
    print(Json.dumps(Report, ensure_ascii=True, indent=2))
    return 1 if Report["SkippedLinks"] else 0


if __name__ == "__main__":
    Sys.exit(Main())

Pending holds folders still to visit. The loop removes one, lists its entries and adds subfolders for later. Regular files contribute a path and size; their contents are not opened.

relative_to(Folder) removes the starting folder from the reported path, and as_posix uses / between folders. Reports keep the same shape even when starting locations differ.

A symbolic link is a path pointing to another file or folder. Links are skipped and named in SkippedLinks; the starting folder cannot itself be a link. Empty folders do not get file records.

The output uses JSON, a text format for named values and lists other programs can read. ensure_ascii=True escapes unusual characters: a newline in a filename becomes \n, and characters outside the basic English set use numbered forms. A JSON reader restores the original values.

The program stops above 10,000 encountered entries, counting files, folders and links. An unsupported entry, such as a named pipe used to pass data between programs, also stops the report rather than silently disappearing.

3. List the folder

Open a command window beside Example and run:

python3 ListFolder.py Example

Use your installation's Python 3 command if it is not named python3. The output is:

{
  "Files": [
    {
      "Path": "Note.txt",
      "Bytes": 3
    },
    {
      "Path": "Sub/Data.txt",
      "Bytes": 2
    }
  ],
  "SkippedLinks": []
}

Files holds paths and sizes. SkippedLinks is empty because this example has no links. An empty folder gives empty lists, not a failure.

The exit code, a small result number another script can check, is 0 for a completed walk without skipped links, 1 with skipped links, or 2 for a command/read error. A failed walk prints an error rather than a partial report.

4. Save the report

Choose a location outside Example:

python3 ListFolder.py Example > ExampleFiles.json

The > asks the command window to save output in a file. Choose a new name because it can replace an existing file. Keeping the report outside the input folder prevents it from listing itself. Keep it private if the names reveal personal or work information.

The program passed 17 checks, including nested and empty folders, sorted sizes, broken links, a link back to the starting folder, unusual names, the entry limit and a rejected named pipe. Tested file contents remained unchanged.

Now you have an inventory, a list of what is present. Matching paths and sizes still do not prove matching contents; use a byte comparison or fingerprint for that next check.

Use a folder that will not change during the walk. It is not frozen, and link skipping does not protect against someone replacing paths while the program runs. The report omits empty folders, permissions, ownership and contents. Reading folder information may affect recorded access times. The entry cap limits collected items, not filename length or runtime.

References

More free code guides