In-Memory File System: Add cd and Relative Path Support
PerplexitySoftware Engineer · Technical ScreenLast updated
A multi-part coding exercise that builds an in-memory file system with directories, files and listings over absolute paths, then adds a cd command and relative path support to every operation. It tests tree data structures, path normalization with dot and dot-dot components, consistent error handling and safely refactoring earlier code.
Implement an in-memory file system as a class, in stages. The early stages build a tree of directories and files addressed by absolute paths. The final stage adds a current working directory with a cd command and requires every operation to accept relative paths as well. That final stage is where the difficulty lies: path handling written for absolute paths has to change without breaking what already works, and relative-path bugs are easy to introduce.
The earlier stages are not specified in detail here, so Part 1 states an assumed baseline API. If your interviewer gives a different one, keep its semantics and apply Part 2 to it. Part 2 is the extension the question builds toward.
Clarifying Questions
- Are file contents plain strings, and does writing to an existing file overwrite it or append to it?
- Should
lsreturn names in sorted order, and what should it return when the path is a file? - How should errors be reported: exceptions, return values, or silently ignored?
- Can paths contain repeated slashes or a trailing slash, or are inputs always well formed?
Part 1 — Baseline file system over absolute paths
Implement this API. Every path is absolute: it starts with /, and / alone is the root.
class FileSystem:
def mkdir(self, path: str) -> None: ...
def write_file(self, path: str, content: str) -> None: ...
def read_file(self, path: str) -> str: ...
def ls(self, path: str) -> list[str]: ...
mkdircreates the directory and any missing parent directories. It is an error if some component of the path is an existing file.write_filecreates the file or overwrites its content. Its parent directory must already exist, and the path must not name a directory.read_filereturns a file's content; the path must name an existing file.lsreturns the names of a directory's entries in sorted order, or a one-element list with the file's own name when the path names a file.
What This Part Should Cover
- A tree in which directories map names to children and files hold content
- A single traversal helper shared by all methods
- Defined behavior for missing paths, a file used as a directory, and the root itself
Part 2 — Add cd and relative paths
Add cd(path), which changes the current working directory, and a pwd() helper that returns the current directory as an absolute path, so the behavior can be tested. The file system starts in /. From now on every method, including cd itself, must accept both absolute paths and relative paths such as docs/a.txt, ./docs or ../shared/b.txt, which are resolved against the current directory.
Clarifying Questions for this Part
- What does
..mean at the root: an error, or stay at the root as a Unix shell does? - If
cdtargets a missing directory or a file, should it fail and leave the current directory unchanged? - Must a path like
missing/../docsfail becausemissingdoes not exist, or may..be resolved purely by text?
What This Part Should Cover
- One resolution function that turns any absolute or relative input into a canonical path, used by every method
- Correct handling of
.,..(including at the root), empty components and trailing slashes cdvalidates its target before changing any state- Tests that send relative paths through every operation, not only through
cd
Hints
Hint 1
One tree, one walk: Decide how directories and files differ in your representation, and write the walk from the root to a node once, so that every method reuses it instead of splitting paths itself.
Hint 2
Count the places that read a path: Before writing `cd`, find every place in your Part 1 code that interprets a path string. Relative paths become a small change only if there is exactly one such place.
Hint 3
Test the resolver on its own: Write a handful of input and expected-output pairs for path resolution alone, covering `.`, `..`, repeated slashes and attempts to go above the root, before running them through the other methods.
Follow-up questions
- Add `rm`. What should happen to a current directory that gets deleted?
- Several users share one file system, each with their own current directory. Where does the current directory live now?
- Symbolic links are added. Why does resolving `..` purely by text become wrong, and how would you resolve paths instead?
- How would you add `~` for a home directory, or a command that returns to the previous directory?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.