Python os Module – The Ultimate Guide (File System, Shell Commands & More)

The os module is one of the most powerful and frequently used built-in modules in Python. It gives your program the ability to interact with the operating system — create/delete/rename files & folders, run shell commands, get environment variables, change working directory, and much more.

In this comprehensive guide we'll cover:

      
  • Most important os functions for everyday use
  •   
  • Running shell commands safely
  •   
  • File & directory creation/deletion/renaming
  •   
  • Executing system commands (shutdown, restart, etc.)
  •   
  • Modern alternatives (pathlib)
  •   
  • Best practices & common pitfalls

1. Quick Reference – Most Useful os Functions

                                                  
Taskos function / patternModern alternative (pathlib)
Get current directoryos.getcwd()Path.cwd()
Change directoryos.chdir(path)Path(path).chdir() (rare)
List directory contentsos.listdir(path)Path(path).iterdir()
Create directoryos.mkdir() / os.makedirs()Path.mkdir(parents=True)
Remove fileos.remove()Path.unlink()
Remove directoryos.rmdir() / os.removedirs()Path.rmdir()
Rename / moveos.rename(src, dst)Path(src).rename(dst)
Check if existsos.path.exists()Path.exists()
Is file / directory?os.path.isfile() / isdir()Path.is_file() / is_dir()
Join paths safelyos.path.join()Path / "file.txt"

2. Running Shell Commands – Three Main Ways

           
MethodModuleReturnsUse whenSecurity note
os.system(cmd)osexit codevery simple one-linersshell injection risk
subprocess.run()subprocessCompletedProcess objectmodern & recommendedsafe with list
subprocess.check_output()subprocessstdout bytesneed outputsame as above
**Best practice 2025 → always use subprocess with list form** ```python import subprocess # Safe (no shell=True) subprocess.run(["ls", "-la"], check=True) # Capture output result = subprocess.run( ["git", "rev-parse", "--short", "HEAD"], capture_output=True, text=True, check=True ) commit_hash = result.stdout.strip() ```

3. Creating Files & Directories

```python from pathlib import Path import os # Modern way (recommended) Path("reports/2025/q1").mkdir(parents=True, exist_ok=True) # Classic way os.makedirs("logs/debug", exist_ok=True) # Create empty file Path("important.txt").touch() # or open("important.txt", "a").close() ```

4. Removing Files & Directories

```python # Single file Path("temp.log").unlink(missing_ok=True) # Empty directory os.rmdir("empty_folder") # Directory + contents (dangerous!) import shutil shutil.rmtree("whole_folder", ignore_errors=True) ```

5. Shutdown and Restart System (cross-platform notes)

```python import os import platform import subprocess def shutdown(): sys = platform.system() if sys == "Windows": os.system("shutdown /s /t 0") elif sys == "Linux" or sys == "Darwin": subprocess.run(["sudo", "shutdown", "-h", "now"], check=False) def restart(): sys = platform.system() if sys == "Windows": os.system("shutdown /r /t 0") elif sys == "Linux" or sys == "Darwin": subprocess.run(["sudo", "reboot"], check=False) ```

Warning: These commands require admin/root privileges on Linux/macOS.

6. Renaming / Moving Files & Directories

```python # Simple rename os.rename("oldname.txt", "newname.txt") # Move + rename Path("documents/report-v1.pdf").rename("archive/report-final-2025.pdf") # Move directory shutil.move("temp_folder", "backup/temp_folder") ```

7. Executing System Commands – Real Examples

```python # Get external IP (cross-platform) def get_public_ip(): try: result = subprocess.run( ["curl", "ifconfig.me"], capture_output=True, text=True, timeout=5 ) return result.stdout.strip() except: return "offline" # Compress folder (Linux/macOS) def compress_folder(folder): subprocess.run(["tar", "-czf", f"{folder}.tar.gz", folder], check=True) # Open file with default application def open_file(path): import webbrowser webbrowser.open(path) ```

Cheat Sheet – os vs pathlib (2026 style)

| Task | os way | pathlib way (preferred) | |-----------------------------|-------------------------------------|-------------------------------------------| | Current dir | os.getcwd() | Path.cwd() | | Join paths | os.path.join(a, b, c) | Path(a) / b / c | | Exists | os.path.exists(p) | Path(p).exists() | | Is file | os.path.isfile(p) | Path(p).is_file() | | Create dirs | os.makedirs(p, exist_ok=True) | Path(p).mkdir(parents=True, exist_ok=True)| | Rename | os.rename(src, dst) | Path(src).rename(dst) | | Remove file | os.remove(p) | Path(p).unlink(missing_ok=True) |

Final Best Practices (2026)

      
  • Prefer pathlib.Path over os.path in new code
  •   
  • Use exist_ok=True / missing_ok=True to avoid annoying errors
  •   
  • Never use os.system() with user input → shell injection
  •   
  • Use subprocess.run(..., check=True) when command failure matters
  •   
  • Always handle FileNotFoundError, PermissionError
  •   
  • Log filesystem operations in production code

Wrapping Up – Level Up Your Filesystem Game

The os module remains a foundational part of Python — but in 2025–2026, the real power comes from knowing when to use it and when to reach for better tools.

Quick recap — your modern toolkit should look like this:

  • Path handling & most filesystem checks/operations → pathlib.Path (cleaner, chainable, cross-platform by default)
  • Running external commands → subprocess.run() with list arguments (safe, flexible, modern default)
  • High-level file copying / recursive delete/move → shutil (still irreplaceable in many cases)
  • Very low-level OS interactions (env vars, process info, low-level file descriptors) → keep using os

By preferring pathlib in the new code, avoiding shell=True pitfalls, and handling exceptions gracefully, you'll write scripts that are:

  • more readable for your future self and teammates
  • safer against injection & permission surprises
  • easier to test and maintain
  • portable across Windows / macOS / Linux with almost zero effort

Whether you're building quick automation scripts, data pipelines, DevOps helpers, backup utilities, or production ETL jobs — mastering this family of modules (os + pathlib + subprocess + shutil) is one of the highest-leverage skills a Python developer can have.

So go ahead — refactor that old script, add some Path objects, make that subprocess call safe, and enjoy how much smoother filesystem code feels in 2026.

Keep shipping clean, reliable automation. You've got this! 🚀📂

Happy coding — and may your directories always be tidy. 😄

Previous Post