Katkat

Design mkdir and ls for a Basic File System

UberSoftware Engineer · Onsite

Last updated

Design an in-memory file system supporting path creation (`mkdir`) and directory listing (`ls`). Tests tree-based data structures, path parsing, and clean object-oriented design.

Design an In-Memory File System

Design an in-memory file system that supports creating directories and listing their contents.

Implement the FileSystem class:

  • FileSystem() Initializes the object of the system with a root directory /.
  • mkdir(path: str) -> bool: Creates directory nodes along the specified absolute path. If intermediate directories in path do not exist, they should be created automatically (similar to mkdir -p). Returns True if the path was successfully created or already exists as a directory. Returns False if creation fails (for instance, if any component of path already exists as a non-directory, or if the path format is invalid).
  • ls(path: str) -> list[str]: Returns a list of the names of all immediate items (directories) located directly inside path, sorted in lexicographical (alphabetical) order. If path does not exist or does not point to a directory, return an empty list [].

Path Format

  • Every valid path is an absolute path that starts with /.
  • Path components consist of lowercase English letters and digits (a-z, 0-9).
  • Consecutive slashes (e.g., //a///b) should be normalized to single delimiters, and trailing slashes should be ignored (e.g., /a/b/ is treated as /a/b).

Examples

fs = FileSystem()

# Listing root initially
fs.ls("/")  # returns []

# Creating nested directories
fs.mkdir("/uber/rides")  # returns True
fs.mkdir("/uber/eats")   # returns True

# Listing contents of /uber
fs.ls("/uber")  # returns ["eats", "rides"]

# Listing root
fs.ls("/")  # returns ["uber"]

# Redundant slashes and trailing slashes
fs.mkdir("//uber///freight/")  # returns True
fs.ls("/uber/")  # returns ["eats", "freight", "rides"]

# Querying a non-existent path
fs.ls("/unknown")  # returns []

Constraints

  • 1 <= path.length <= 500
  • Directory names contain only lowercase English letters (a-z) and digits (0-9).
  • At most 10^4 total calls will be made to mkdir and ls.

Edge Cases

  • Querying or creating the root path /.
  • Paths containing redundant slashes (e.g., /a//b).
  • Querying non-existent paths with ls.

Hints

Hint 1

Model the file system as an n-ary tree or trie where each node represents a directory storing a map of child names to child nodes.

Hint 2

Write a helper function to sanitize and split paths by `/`, filtering out empty strings to handle redundant slashes cleanly.

Hint 3

Keep child pointers sorted upon retrieval, or store them in a hash map and sort the keys when `ls` is called.

Follow-up questions

  • How would you extend this system to support files with `create_file(path, content)` and `read_file(path)`?
  • How would you support concurrent reads and writes across different branches of the directory tree efficiently?
  • How would you implement relative paths, including handling `.` (current directory) and `..` (parent directory)?