Scripts and file automation

Create a CSV list of files in a folder

Scan subfolders and record file paths, extensions, sizes, and modification times in a table. Start with 4 small example files while keeping the originals and existing results intact.

Show contents

This translation was generated by AI. Check the code, units, and numbers against the original. Native-speaker review has not yet been completed for each language. 한국어

Who this is forPython beginners who have been manually listing the number and locations of documents in a folder

What you need
  • Install Python 3.12 or later and check the version in a terminal with python --version.
  • Extract the example ZIP into a new folder. Do not run the example from inside the ZIP archive.
  • Open a terminal in the folder containing example.py. If the python command is unavailable on Windows, use py. On macOS or Linux, use python3 if your environment requires it.
  • No external packages or accounts are needed. The included files are synthetic data created for this tutorial.

01Create your first list with four files

Creating an output folder is not enough to call this task complete. The CSV must contain each of the four original files exactly once, the listed sizes must total 63 bytes, and the original contents must remain unchanged. Check these conditions with the included data before moving on to your own work folder.

  1. Find example.py, README.txt, and the sample_files folder in the extracted folder.
  2. Open sample_files and check readme.txt, empty.txt, and the docs and reports subfolders. empty.txt is intentionally empty.
  3. Run the command below once in the terminal. Do not move or edit the input files while it runs.
  4. When the completion message and output path appear, open outputs/file_list.csv.
bash
python example.py

02Understand the paths and columns

The code starts from the location of example.py, not the current terminal folder. It scans only sample_files under BASE, so you can move the whole example folder as long as its internal layout stays the same. outputs sits outside the scanned folder so the result CSV does not enter the input list on a later run.

ColumnMeaningWhat to check
relative_pathPath relative to sample_filesFiles with the same name are distinguishable if they are in different folders.
extensionThe last extension, in lowercaseNo extension is shown as (없음); tar.gz is shown as .gz.
size_bytesFile size as an integer number of bytes0 means an empty file, not a missing value.
modified_utcFile modification time in UTCThe trailing +00:00 means UTC, which differs from Korean local time.

relative_path uses forward slashes for readability across operating systems. Results are sorted by this path. They do not depend on the internal file traversal order, making it easier to compare row order for the same input.

03Full code used in this example

collect_files gathers file information, and main writes a new CSV. The code does not create outputs until input checks are complete. If it encounters an unreadable folder or a link, it stops rather than saving a partial list as a successful result.

example.py
"""sample_files를 읽어 outputs/file_list.csv에 목록을 기록합니다. 원본은 변경하지 않습니다."""

import csv
import os
import sys
from datetime import datetime, timezone
from pathlib import Path

BASE = Path(__file__).resolve().parent
INPUT = BASE / "sample_files"
OUTPUT = BASE / "outputs"
FIELDS = ["relative_path", "extension", "size_bytes", "modified_utc"]


def is_link(path):
    # Windows 연결 디렉터리(junction)도 Python 3.12 이상에서는 거부합니다.
    return path.is_symlink() or getattr(path, "is_junction", lambda: False)()


def collect_files(folder):
    if is_link(folder) or not folder.is_dir():
        raise ValueError("sample_files는 실제 폴더여야 합니다.")
    rows = []

    def stop_on_error(error):
        raise error

    # 하위 폴더까지 읽되, 링크를 따라 다른 폴더로 나가지 않습니다.
    for root, dirs, files in os.walk(folder, followlinks=False, onerror=stop_on_error):
        root = Path(root)
        for name in dirs + files:
            if is_link(root / name):
                raise ValueError(f"링크는 처리하지 않습니다: {root / name}")
        for name in sorted(files):
            path = root / name
            if not path.is_file():
                raise ValueError(f"일반 파일이 아닙니다: {path}")
            stat = path.stat()
            rows.append({
                "relative_path": path.relative_to(folder).as_posix(),
                "extension": path.suffix.lower() or "(없음)",
                "size_bytes": stat.st_size,
                "modified_utc": datetime.fromtimestamp(
                    stat.st_mtime, timezone.utc
                ).isoformat(timespec="seconds"),
            })
    return sorted(rows, key=lambda row: row["relative_path"])


def main():
    if OUTPUT.exists() or OUTPUT.is_symlink():
        raise FileExistsError("outputs가 이미 있습니다. 기존 결과를 옮긴 뒤 실행하세요.")
    rows = collect_files(INPUT)  # 모두 읽은 뒤에만 출력 폴더를 만듭니다.
    OUTPUT.mkdir()
    target = OUTPUT / "file_list.csv"
    # x는 기존 파일을 덮어쓰지 않는 모드입니다. BOM은 한글 CSV 열기에 도움을 줍니다.
    with target.open("x", encoding="utf-8-sig", newline="") as stream:
        writer = csv.DictWriter(stream, fieldnames=FIELDS)
        writer.writeheader()
        writer.writerows(rows)
    print(f"완료: {len(rows)}개 파일, 합계 {sum(row['size_bytes'] for row in rows)}바이트")
    print(target)
    return 0


if __name__ == "__main__":
    try:
        raise SystemExit(main())
    except (OSError, ValueError) as error:
        print(f"중지: {error}", file=sys.stderr)
        raise SystemExit(2)

csv.DictWriter handles CSV delimiters and quoting. The file is saved with newline set to an empty string and a UTF-8 BOM. The output file is opened in x mode so it will not overwrite a file that already exists. This example first checks whether the outputs folder itself exists.

04Check the four rows and total size

relative_pathextensionsize_bytes
docs/agenda.txt.txt15
empty.txt.txt0
readme.txt.txt17
reports/sales.csv.csv31

The table totals 15 + 0 + 17 + 31 = 63 bytes. The terminal also displays “완료: 4개 파일, 합계 63바이트” (complete: four files, sixty-three bytes total). The first line of the CSV contains column names, so a spreadsheet shows five rows including the header. Do not forget to count empty.txt.

05Check the originals as well as the list

  1. Match each of the four paths in the CSV to its actual location in sample_files. The docs and reports folders themselves are not included as data rows.
  2. Check that the empty file is included with a size of 0 bytes and that the extensions are .txt and .csv.
  3. Open sample_files/readme.txt and check that the original text Sample inventory is still there.
  4. Run the same command again. It should stop with “outputs가 이미 있습니다” (outputs already exists), and the first result should remain intact.

Failure conditions are part of the design. Do not remove the output-protection code just because it blocks a repeated run. To keep the previous results, rename outputs to a name containing a date before running again, or extract the ZIP into a new folder to start a new test.

06Apply it to your own folder

Do not point the example at your entire work folder at first. Put a few representative files in a copy of sample_files. Path objects handle filenames containing Korean characters or spaces. Symbolic links and directory junctions that point elsewhere are outside the supported scope, so use a small copy containing regular files.

  1. Keep the existing example inputs and results, and create a new practice folder.
  2. Place 5~10 files in sample_files so you can count them by hand. Include one level of subfolders as well.
  3. Generate the list and check that the relative paths point to the expected locations.
  4. Increase the number of files while keeping the checked rules unchanged. File size can differ from content length, so keep the unit as bytes.

If the input folder is empty, the script creates a header-only CSV and reports a file count of 0. This differs from stopping because the folder is missing. An empty folder can be a valid work state, so distinguish the two when interpreting results.

07Resolve common errors

SymptomPossible causeNext step
python command not foundA problem with the Python launcher installation or path settingsCheck python --version first, and try py on Windows.
sample_files must be a real folderThe folder is missing or a link is being usedCheck that you extracted the entire ZIP and restore a real folder.
outputs already existsResults from a previous run are still presentMove the existing results somewhere safe, then run again.
Korean text appears garbledThe program opening the file is interpreting its encoding incorrectlySelect UTF-8 when importing the CSV, and do not modify the original.
Read permission errorAn inaccessible folder or locked pathNarrow the scope to an accessible practice copy first.

08What this list does and does not tell you

The result contains file information observed during the run. It is neither a duplicate-content check nor a backup you can restore from. Two documents with the same file size can have different contents. If you need hash comparisons, define that as a separate task and add the required columns.

This beginner example does not cover other programs changing names or contents during a scan, network-drive delays, or collecting very large numbers of files in memory. A disk-write failure can leave an incomplete outputs folder, so check both the completion message and the number of result rows.

Execution and verification record

2026-09-19 · Windows 11 · CPython 3.12.14 · No additional packages · Run in a temporary copy of the distribution

  • Confirmed 4 files, including files in nested folders, totaling 63 bytes
  • An empty input folder produces a header-only CSV
  • Missing input folders and an existing outputs folder are rejected
  • Confirmed independence from the working directory by running from a different folder
  • Confirmed identical SHA-256 hashes for input files before and after execution
Verification limits
  • Not run on macOS or Linux.
  • Modification times may change after extraction.
  • Concurrent file changes and insufficient disk space were not tested.

Site-wide writing and verification principles

Example files to run yourself

Includes code, input data, and instructions. Extract the ZIP and read README.txt first.

Download example ZIP

Example code, filenames, and input keys remain unchanged. Refer to the commands and checking steps in the translated article as well.

Practice materials created for this site · Keep your originals separately before running.

References

The explanations and examples were written for this site. See the official sources below for the related behavior and concepts.