November 2, 2026
Learning Cybersecurity from Scratch with Breachlab — Ghost Level 1: The File You Can’t Open by Its…
Day 2 of my Breachlab Learning Journey | Why a filename that starts with a dash or contains a space breaks a perfectly normal command, and…

By Someone
6 min read
Day 2 of my Breachlab Learning Journey | Why a filename that starts with a dash or contains a space breaks a perfectly normal command, and four ways to tell the shell exactly what you mean
Disclaimer: This series is for educational purposes only. Everything here happens on Breachlab's own practice targets, which exist to be attacked legally. Don't try these techniques on systems you don't own or don't have written permission to test. Following Breachlab's guidelines, I won't share passwords, flags or a copy-paste solution. Every example below runs on a small practice folder you build yourself, so you learn the technique and still solve the real level on your own.
You log in. You run ls. The file you need is sitting right there, plainly listed.
You type cat and the filename, hit Enter, and... nothing. The cursor just blinks at you. Or you get an error saying the file doesn't exist, about a file you can literally see.
That was my first ten minutes on Ghost Level 1, and honestly it was a more useful lesson than any of the "find the hidden thing" levels. Nothing is hidden here. Nothing is locked. The only thing standing between you and the password is how your shell reads what you typed.
This is Day 2 of my Breachlab Learning Journey, where I'm working through Breachlab's tracks level by level and documenting what each one actually teaches. On Day 1 (Ghost Level 0), the job was getting connected over SSH and learning to look around a box before touching anything. Today builds directly on that: you know how to find files, and now you find out that finding a file and naming it correctly are two different skills.
Today's Topics
- Why some filenames get mistaken for command options
- Why a space in a filename quietly turns one argument into two
- Four reliable ways to refer to an awkward file
- A habit for spotting trouble before you hit Enter
First, Build a Practice Folder
I'm not going to walk you through the real level, so let's build something with the same kinds of problems. On any Linux machine or VM, run this:
mkdir -p ~/lab/ghost1 && cd ~/lab/ghost1
echo "practice value one" > ./-
echo "practice value two" > ./-v
echo "practice value three" > "./field notes.txt"
ls -lamkdir -p ~/lab/ghost1 && cd ~/lab/ghost1
echo "practice value one" > ./-
echo "practice value two" > ./-v
echo "practice value three" > "./field notes.txt"
ls -laYou now have three files whose names are deliberately annoying: one called just -, one called -v, and one with a space in it. The real level uses its own filename and its own twist, so treat these as training weights, not the answer.
Problem 1: The Filename That Looks Like an Option
Try reading the second file the obvious way:
cat -vcat -vYour terminal just sits there. It hasn't frozen; cat is waiting for you to type something. Press Ctrl + C to get out.
Here's what happened. Almost every Linux command treats an argument starting with - as an option, a switch that changes how the command behaves. -v happens to be a real option for cat ("show non-printing characters"). So cat read your filename, decided it was a setting, found no actual file to read, and fell back to reading from your keyboard.
The lone - file trips you up in a similar way. By long-standing Unix convention, a single - on its own means "standard input": read from the keyboard or a pipe instead of a file. So cat - doesn't open the file named - either. It waits for you to type.
The file isn't missing. The command just never looked for it, because it understood your filename as an instruction.
Problem 2: The Filename With a Space
Now the third file:
cat field notes.txtcat field notes.txtThis time you get two errors, one for field and one for notes.txt. Before cat even runs, your shell splits what you typed on spaces to decide where each argument starts and ends. So cat was handed two separate names, and neither exists.
The space is perfectly legal in a filename. Linux allows almost any character in one, but the shell has its own rules about what a space means on a command line, and those rules win unless you override them.
Four Ways to Tell the Shell What You Mean
Every one of these fixes does the same thing in a different way: it removes the ambiguity, so the command can only read your argument as a filename.
1. Give it a path
cat ./-v
cat ./-cat ./-v
cat ./-./ means "in the current directory." The argument now starts with a dot, not a dash, so no command will ever mistake it for an option. This is the fix I reach for first because it works everywhere, even with older or unusual tools.
2. Use the double dash
cat -- -vcat -- -vA bare -- is a widely followed convention that means "options end here; everything after this is a filename." Most standard Linux tools honor it. It's very handy in scripts, but not every program supports it, so test it before you rely on it.
One catch: cat -- - still reads from standard input, because many tools treat a lone - as "stdin" even after --. For that particular name, the path fix is the reliable one.
3. Quote or escape it
cat "field notes.txt"
cat field\ notes.txtcat "field notes.txt"
cat field\ notes.txtQuotes tell the shell "this whole thing is one argument." A backslash does the same for a single character, so \ means "a literal space, don't split here." Quoting fixes the space problem, but not the dash problem: cat "-v" still gets read as an option, because the quotes are removed before cat ever sees the text.
4. Redirect it in
cat < -cat < -With <, the shell opens the file and feeds its contents to the command. The command never sees a filename at all, so it has nothing to misread. It's a neat trick, and it's useful to understand even when you don't need it.
A Habit Worth Building: Look Before You Type
Most of the pain on this level comes from assuming a filename is "normal." Two small checks help you catch the weird ones before you hit Enter:
ls -Q # wraps every name in quotes, so spaces and odd characters stand out
ls -b # shows escapes for special characters, like field\ notes.txt
file ./* # tells you what each file actually containsls -Q # wraps every name in quotes, so spaces and odd characters stand out
ls -b # shows escapes for special characters, like field\ notes.txt
file ./* # tells you what each file actually containsAnd use Tab completion. Type the first character or two and press Tab; the shell fills in the name and adds whatever escaping it needs. Half the time, the shell is quietly showing you the answer to "how do I type this name safely?"
When you try the actual level, slow down at the ls step. Look at exactly what the filename is, work out which problem it causes (option? standard input? splitting? more than one?), then pick the fix that removes that ambiguity. That's the entire skill, and it's yours to apply.
Key Takeaway
A command line isn't just text. It's text the shell splits into arguments, which the command then sorts into options and files. Ghost Level 1 lives in the gap between those two steps. A leading dash makes a filename look like an option, a lone dash means standard input, and a space splits one name into two. Every fix (a ./ path, --, quotes or escapes, or < redirection) works by taking away the command's room to guess.
This matters well beyond one wargame level. When attacker-controlled filenames reach scripts that don't handle them carefully, this exact confusion stops being a nuisance and becomes a vulnerability. I dig into that history, and the standards that explain why Linux behaves like this, in today's theory companion:
Understanding Linux Command-Line Parsing — The Theory Behind Ghost Level 1
The Breachlab Journey Continues
One level at a time, this series works through Breachlab's tracks, from Ghost's Linux fundamentals toward post-exploitation, web, cloud and Active Directory. Each level gets a practical guide like this one and a theory companion explaining the "why."
Breachlab is free and runs entirely on donations. If it's teaching you something, you can support it here: breachlab.org/donate
Watch the deep dive
Follow along with the complete Breachlab playlist on YouTube: Breachlab playlist on Assert True. The channel is Assert True on YouTube.
GitHub Repository
My notes and progress for every level live here: github.com/Someone-anon-coder/Breachlab
Follow the complete series
- Breachlab Ghost I list on Medium: every Breachlab guide and theory article in one place
- Cybersecurity list on Medium: my wider cybersecurity learning notes
My other learning series
Arbiter (Java) Guide · Arbiter (Java) Theory · Python Guide · Python Guide Theory · GoLang Guide · GoLang Guide Theory · My Progress — Matplotlib
What's Next?
On Day 3, we move to Ghost Level 2: files that don't show up in a normal listing at all, why Linux hides some names by default, and how to stop trusting the first ls you run.
Happy hacking! 🛡️