Python
os.makedirs
file path
tilde
user directory

os.makedirs doesn't understand in my path

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

os.makedirs() does not expand the ~ (tilde) character because tilde expansion is a shell feature, not a filesystem feature. Python's file operations treat ~ as a literal directory name. To resolve ~ to the user's home directory, call os.path.expanduser() before passing the path to os.makedirs(). This applies to all os and open() calls, not just makedirs.

The Problem

python
1import os
2
3# This creates a literal directory named "~" in the current directory
4os.makedirs("~/projects/myapp", exist_ok=True)
5
6# You now have: ./~/projects/myapp/ (a directory literally named ~)
7# NOT: /home/username/projects/myapp/

The shell expands ~ to /home/username when you type mkdir ~/projects, but Python does not.

The Fix: os.path.expanduser()

python
1import os
2
3path = "~/projects/myapp"
4expanded = os.path.expanduser(path)
5print(expanded)  # /home/username/projects/myapp (Linux/Mac)
6                  # C:\Users\username\projects\myapp (Windows)
7
8os.makedirs(expanded, exist_ok=True)

Always call expanduser() before any file operation that receives a user-provided path.

Using pathlib (Modern Approach)

python
1from pathlib import Path
2
3# expanduser() is a method on Path objects
4path = Path("~/projects/myapp").expanduser()
5print(path)  # /home/username/projects/myapp
6
7# Create the directory
8path.mkdir(parents=True, exist_ok=True)
9
10# Works for files too
11config = Path("~/.config/myapp/config.json").expanduser()
12config.parent.mkdir(parents=True, exist_ok=True)
13config.write_text('{"key": "value"}')

pathlib.Path.expanduser() is the modern replacement for os.path.expanduser().

Expanding Environment Variables Too

Paths may also contain environment variables like $HOME or %USERPROFILE%:

python
1import os
2
3# Expand both ~ and environment variables
4path = "$HOME/projects/myapp"
5expanded = os.path.expandvars(os.path.expanduser(path))
6print(expanded)  # /home/username/projects/myapp
7
8# Or use a helper that handles both
9def resolve_path(path):
10    return os.path.abspath(os.path.expandvars(os.path.expanduser(path)))
11
12print(resolve_path("~/projects"))
13# /home/username/projects
14
15print(resolve_path("$HOME/projects"))
16# /home/username/projects

Other Functions Affected

~ is not expanded by any Python file function — not just makedirs:

python
1import os
2
3# ALL of these treat ~ as literal
4os.path.exists("~/file.txt")          # Checks for ./~/file.txt
5open("~/file.txt")                     # Opens ./~/file.txt
6os.listdir("~/projects")              # Lists ./~/projects/
7os.remove("~/temp.txt")               # Removes ./~/temp.txt
8os.rename("~/old.txt", "~/new.txt")   # Renames in ./~/
9
10# Fix: expand first
11os.path.exists(os.path.expanduser("~/file.txt"))
12open(os.path.expanduser("~/file.txt"))

Getting the Home Directory Directly

python
1import os
2from pathlib import Path
3
4# os module
5home = os.path.expanduser("~")
6print(home)  # /home/username
7
8# pathlib
9home = Path.home()
10print(home)  # /home/username
11
12# Environment variable
13home = os.environ.get("HOME")  # Linux/Mac
14home = os.environ.get("USERPROFILE")  # Windows
15
16# Build paths from home
17config_dir = Path.home() / ".config" / "myapp"
18config_dir.mkdir(parents=True, exist_ok=True)

Cross-Platform Path Building

python
1from pathlib import Path
2
3# Works on Windows, Mac, and Linux
4app_data = Path.home() / "AppData" / "Local" / "MyApp"  # Windows
5app_data = Path.home() / ".config" / "myapp"              # Linux
6app_data = Path.home() / "Library" / "Application Support" / "MyApp"  # macOS
7
8# Platform-aware approach
9import platform
10
11def get_app_dir(app_name):
12    system = platform.system()
13    if system == "Windows":
14        return Path.home() / "AppData" / "Local" / app_name
15    elif system == "Darwin":
16        return Path.home() / "Library" / "Application Support" / app_name
17    else:
18        return Path.home() / f".{app_name.lower()}"
19
20app_dir = get_app_dir("MyApp")
21app_dir.mkdir(parents=True, exist_ok=True)

Common Pitfalls

  • Assuming ~ works in Python like it does in the shell: The shell expands ~ before the program sees it. Python receives the raw string. Always call expanduser() or use Path.expanduser() for paths containing ~.
  • Creating a literal ~ directory: If you call os.makedirs("~/something") without expanding, Python creates a directory literally named ~ in the current working directory. This is confusing and hard to delete (use rm -rf './~' with quotes).
  • Forgetting expandvars() for $HOME: expanduser() only handles ~. Environment variables like $HOME or $USER require os.path.expandvars(). Chain both for maximum compatibility.
  • Hardcoding /home/username: Hardcoded home paths break on other machines and operating systems. Always use Path.home(), os.path.expanduser("~"), or os.environ["HOME"].
  • Not using exist_ok=True: os.makedirs() raises FileExistsError if the directory already exists (default behavior). Always pass exist_ok=True unless you specifically want to fail on existing directories.

Summary

  • os.makedirs() does not expand ~ — it creates a literal directory named ~
  • Call os.path.expanduser(path) or Path(path).expanduser() before any file operation
  • Use Path.home() to get the home directory without string manipulation
  • expanduser() handles ~, expandvars() handles $HOME — chain both for full expansion
  • This applies to all Python file functions: open(), os.path.exists(), os.listdir(), etc.
  • Prefer pathlib.Path over os.path for modern, readable path handling

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.