Python os: Files, Folders, and Environment

Updated on: August 20, 2026
Reading time: 5 minutes
Manipulação de arquivos e pastas usando módulo os em Python

Python programs often need to interact with the operating system. A script may create folders, list files, rename reports, read environment variables, or organize downloads. The Python os module provides standard tools for these tasks without requiring an external package.

This guide explains the most useful parts of os and os.path for beginners. You will learn how to inspect the current directory, create nested folders, join paths safely, rename and delete files, walk through directory trees, read environment variables, and build a practical file organizer.

For newer object-oriented path handling, also read the companion guide to Python pathlib. The two modules can work together: os remains important for environment variables, process information, permissions, and many operating-system operations, while pathlib often produces clearer path code.

What Is the Python os Module?

os is part of Python’s standard library. It exposes portable operating-system interfaces so the same program can perform many file and directory tasks on Windows, macOS, and Linux.

import os

print(os.name)
print(os.getcwd())

os.name gives a broad platform identifier such as "nt" on Windows or "posix" on Unix-like systems. For detailed platform information, use the separate platform module.

The official Python os documentation lists the full API. The related os.path reference covers pathname operations.

Find and Change the Current Working Directory

The current working directory is the folder Python uses to resolve relative paths.

import os

current_directory = os.getcwd()
print(current_directory)

os.chdir("data")
print(os.getcwd())

os.chdir() changes the process’s working directory. Use it carefully because every later relative path will be interpreted from the new location. In many scripts, keeping the working directory unchanged and building explicit paths is easier to reason about.

Path confusion is a common cause of missing-file errors. The guide to fixing Python FileNotFoundError explains how to diagnose those cases.

List Files and Folders

os.listdir() returns the names inside a directory:

import os

for name in os.listdir("."):
    print(name)

The result includes files and subdirectories but not their full paths. Join each name to the parent directory before inspecting it.

base_directory = "reports"

for name in os.listdir(base_directory):
    full_path = os.path.join(base_directory, name)

    if os.path.isfile(full_path):
        print("File:", full_path)
    elif os.path.isdir(full_path):
        print("Folder:", full_path)

Join Paths Safely with os.path.join()

Do not build filesystem paths by manually adding slashes. Different operating systems use different separators, and duplicate separators are easy to introduce.

folder = "exports"
filename = "sales.csv"

path = os.path.join(folder, filename)
print(path)

os.path.join() uses the correct separator for the current platform. The companion guide on pathlib paths shows the modern alternative: Path("exports") / "sales.csv".

Create Directories

os.mkdir() creates one folder. Its parent must already exist.

os.mkdir("output")

os.makedirs() can create an entire nested structure:

os.makedirs(
    os.path.join("project", "logs", "archive"),
    exist_ok=True,
)

exist_ok=True prevents an error when the final directory already exists. It does not hide every possible failure: permissions and invalid paths can still raise exceptions.

Rename and Move Files

os.rename() can rename an item or move it to another location on the same filesystem.

old_path = os.path.join("reports", "draft.csv")
new_path = os.path.join("reports", "sales-2026.csv")

os.rename(old_path, new_path)

When moving files between different disks or filesystems, shutil.move() is usually more flexible. See the guide to copying and moving files with shutil for complete examples.

Delete Files and Empty Folders

file_path = os.path.join("temp", "old-report.txt")

if os.path.isfile(file_path):
    os.remove(file_path)

Use os.rmdir() to remove an empty directory:

empty_folder = os.path.join("temp", "empty")

if os.path.isdir(empty_folder):
    os.rmdir(empty_folder)

These operations normally bypass the desktop recycle bin. Confirm the path before deleting anything, especially when the value comes from user input or configuration. To remove a directory tree, use shutil.rmtree() only after adding strong safeguards.

Inspect Path Components

path = os.path.join("data", "archive", "customers.csv")

print(os.path.basename(path))   # customers.csv
print(os.path.dirname(path))    # data/archive
print(os.path.splitext(path))   # (.../customers, .csv)
print(os.path.abspath(path))

splitext() separates the final extension from the rest of the path. It is useful for classifying files by type, but remember that a suffix is only a naming convention; it does not prove the actual file format.

Check Whether a Path Exists

path = os.path.join("config", "settings.json")

if os.path.exists(path):
    print("The path exists")

if os.path.isfile(path):
    print("It is a file")

if os.path.isdir(path):
    print("It is a directory")

Existence checks can help produce friendly messages, but they do not replace exception handling. Another process may change the file after your check. Open or modify the resource inside an appropriate try/except block when reliability matters.

Walk Through a Directory Tree

os.walk() recursively visits a directory and yields the current folder, its subfolder names, and its filenames.

for current_folder, subfolders, filenames in os.walk("project"):
    print("Folder:", current_folder)

    for filename in filenames:
        file_path = os.path.join(current_folder, filename)
        print("  ", file_path)

This is useful for backups, storage reports, code searches, and bulk conversion. For recurring backup work, the automatic Python backup guide provides a larger workflow.

Read and Set Environment Variables

Environment variables store configuration outside source code. They are commonly used for modes, service addresses, and secret identifiers.

import os

environment = os.getenv("APP_ENV", "development")
api_url = os.getenv("API_URL")

print(environment)
print(api_url)

os.getenv() returns None or a supplied default when the variable is missing. You can also access os.environ like a mapping:

os.environ["APP_MODE"] = "test"
print(os.environ["APP_MODE"])

A value assigned this way affects the current process and child processes, not the user’s permanent system configuration. Never print secrets or commit them to source control. The guide to reading environment variables safely covers validation and .env files.

Get File Metadata

path = os.path.join("reports", "sales.csv")
metadata = os.stat(path)

print("Size:", metadata.st_size)
print("Modified timestamp:", metadata.st_mtime)

os.stat() returns metadata such as size, timestamps, and permission information. Timestamp values are seconds since the platform epoch; use datetime to convert them into readable dates.

Practical Project: Organize Files by Extension

The following script scans one directory and moves files into category folders. It uses os for inspection and directory creation, and shutil.move() for robust moves.

import os
import shutil


CATEGORIES = {
    "images": {".jpg", ".jpeg", ".png", ".gif", ".webp"},
    "documents": {".pdf", ".docx", ".txt", ".xlsx", ".csv"},
    "archives": {".zip", ".rar", ".7z", ".tar", ".gz"},
    "code": {".py", ".js", ".html", ".css", ".json"},
}


def category_for(filename):
    extension = os.path.splitext(filename)[1].lower()

    for category, extensions in CATEGORIES.items():
        if extension in extensions:
            return category

    return "other"


def unique_destination(folder, filename):
    stem, extension = os.path.splitext(filename)
    candidate = os.path.join(folder, filename)
    number = 1

    while os.path.exists(candidate):
        candidate = os.path.join(
            folder,
            f"{stem}-{number}{extension}",
        )
        number += 1

    return candidate


def organize_files(directory):
    directory = os.path.abspath(directory)

    if not os.path.isdir(directory):
        raise NotADirectoryError(directory)

    moved = 0

    for filename in os.listdir(directory):
        source = os.path.join(directory, filename)

        if not os.path.isfile(source):
            continue

        category = category_for(filename)
        destination_folder = os.path.join(directory, category)
        os.makedirs(destination_folder, exist_ok=True)

        destination = unique_destination(
            destination_folder,
            filename,
        )

        shutil.move(source, destination)
        moved += 1
        print(f"Moved {filename} to {category}/")

    return moved


if __name__ == "__main__":
    total = organize_files("downloads-test")
    print(f"Finished: {total} files moved")

The function avoids overwriting an existing file by adding a number to the destination name. For unattended use, replace or supplement print() with Python logging.

os vs. pathlib vs. shutil

ModuleBest suited for
osEnvironment variables, process and platform operations, directory functions, low-level OS interfaces.
os.pathString-based path inspection and manipulation.
pathlibReadable, object-oriented path and file operations.
shutilHigh-level copying, moving, archiving, and directory-tree operations.

You do not have to choose only one. Real applications often use all three where each is clearest.

Common Mistakes

  • Concatenating paths with hard-coded slashes.
  • Assuming the working directory is the script directory.
  • Deleting a path without confirming what it points to.
  • Ignoring permissions and file-lock errors.
  • Using os.rename() for cross-filesystem moves without a fallback.
  • Logging environment-variable secrets.
  • Checking existence but not handling a later operation failure.

Frequently Asked Questions

Do I need to install os?

No. It is included in Python’s standard library.

How do I get the script’s directory?

Use os.path.dirname(os.path.abspath(__file__)). In interactive environments, __file__ may not exist.

How do I create nested folders?

Use os.makedirs(path, exist_ok=True).

Can os move a file?

os.rename() can move or rename files in supported situations. Use shutil.move() for a higher-level solution, especially across filesystems.

Is pathlib replacing os?

No. Pathlib replaces many string-based path tasks, but os still exposes operating-system features that pathlib does not.

Conclusion

The Python os module is a foundational tool for automation and system interaction. Learn getcwd(), listdir(), makedirs(), os.path.join(), environment variables, and safe deletion first. Then add os.walk(), metadata, permissions, and process features as your projects require them.

Use explicit paths, validate destructive operations, and handle exceptions around real filesystem work. Those habits make scripts safer and easier to run on different computers.

Share:

Facebook
WhatsApp
Twitter
LinkedIn

Article content

    Related articles

    Document and inbox representing local email stores with Python mailbox
    Libraries and Modules
    Foto de perfil de Leandro Hirt da Academify

    Python mailbox: Local Email Stores

    Learn Python mailbox to read, create, and migrate Maildir, mbox, and MH stores with locking, flags, message parsing, and safe

    Ler mais

    Tempo de leitura: 5 minutos
    12/08/2026
    Text editor representing formatting with Python textwrap
    Libraries and Modules
    Foto de perfil de Leandro Hirt da Academify

    Python textwrap: Format Text

    Learn Python textwrap to wrap, fill, shorten, indent, and dedent text with controlled width, whitespace, long words, and reusable settings.

    Ler mais

    Tempo de leitura: 4 minutos
    10/08/2026
    Folder and magnifying glass representing file-name filters with Python fnmatch
    Libraries and Modules
    Foto de perfil de Leandro Hirt da Academify

    Python fnmatch: Filter File Names

    Learn Python fnmatch to filter file names with shell wildcards, control case sensitivity, exclude patterns, and distinguish glob from regex.

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Monitor with binary data representing compact numeric arrays in Python
    Libraries and Modules
    Foto de perfil de Leandro Hirt da Academify

    Python array: Compact Numeric Data

    Learn Python array for compact numeric storage, binary files, byte order, memory views, and safe buffer interoperability.

    Ler mais

    Tempo de leitura: 6 minutos
    10/08/2026
    Color wheel representing RGB, HSV, and HLS conversions with Python colorsys
    Libraries and Modules
    Foto de perfil de Leandro Hirt da Academify

    Python colorsys: RGB, HSV, and HLS

    Learn Python colorsys to convert colors between RGB, HSV, HLS, and YIQ, generate palettes, and avoid scale and precision mistakes.

    Ler mais

    Tempo de leitura: 5 minutos
    09/08/2026
    Configuration icon representing plist files with Python plistlib
    Libraries and Modules
    Foto de perfil de Leandro Hirt da Academify

    plistlib: Read and Write Apple Plist Files

    Learn Python plistlib to read and write XML and binary plist files, validate data, handle dates, bytes, and UIDs safely.

    Ler mais

    Tempo de leitura: 6 minutos
    08/08/2026