Skip to content
VLSI Mentor

Linux & Bash · Part I · Module 2 · The Filesystem and Paths

The Working Directory, and the Shorthands . .. and ~

Chapter 2.2 left one piece unexplained: the working directory that completes every relative path. This chapter makes it precise, then adds the three shorthands that real paths are full of. Two of them are genuine directories that the filesystem stores and you can list. The third is not a directory at all — it is text that Bash swaps out before the command ever runs. That difference sounds like trivia and is not: it is what explains why a script sitting in front of you refuses to run until you put two extra characters in front of its name.

Foundation16 min readLinuxBashPart IFundamentalsPaths

Part I · Module 2 · Chapter 2.3 · The Working Directory, and the Shorthands

1. The Working Directory Belongs to a Process

Chapter 1.7 established that a process is a running program with its own state, and that a child gets a copy of some of that state. One of the things in that state is the working directory.

So, precisely:

  • every process has exactly one working directory;
  • your shell is a process, so your shell has one;
  • a program your shell starts is a different process, and it starts with a copy of your shell's;
  • changing the copy does not change yours.

That last point is Chapter 1.7's rule, and it is why cd had to be a builtin. Nothing new is being claimed here — the same fact is simply being applied to the thing it was always about.

pwd from Chapter 1.4 asks the shell for its own value:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project

The value is always an absolute path. There is no such thing as being "relatively located".

2. . — Here

A single dot means this directory — whichever directory the path is being resolved from.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
.
./alu.sv
./rtl

Applying Chapter 2.2's rule from /home/engineer/project:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
/home/engineer/project  +  .           →  /home/engineer/project
/home/engineer/project  +  ./rtl       →  /home/engineer/project/rtl

So ./rtl and rtl name exactly the same directory. The dot adds nothing to the meaning.

Which raises a reasonable question: if it adds nothing, why does it exist? Two reasons, and §7 is about the second.

The first is that it gives you a way to name the current directory, rather than merely resolve from it. Some commands need a location as an argument, and "here" has to be spellable:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project

$ ls .
docs  rtl  scripts  sim

3. .. — The Parent

Two dots mean the parent directory — the directory that contains this one, in Chapter 2.1's sense.

From /home/engineer/project/rtl:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
/home/engineer/project/rtl  +  ..  →  /home/engineer/project

Two dots can be used in the middle of a longer path, and that is where they earn their keep:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
/home/engineer/project/sim  +  ../rtl  →  /home/engineer/project/rtl

Read that in two steps: .. moves up from sim to project, then rtl moves down into rtl. Figure 1 walks it one step at a time.

Four steps. Start in /home/engineer/project/sim. Two dots move up one level to /home/engineer/project. The name rtl moves down into /home/engineer/project/rtl. The name alu.sv names the file /home/engineer/project/rtl/alu.sv.Resolving ../rtl/alu.sv one step at a time01START HEREworking directory: /home/engineer/project/sim02UP ONE LEVEL.. lands on /home/engineer/project03DOWN ONE LEVELrtl lands on /home/engineer/project/rtl04THE FILEalu.sv is /home/engineer/project/rtl/alu.sv
Figure 1 — resolving one relative path, step by step, from a stated starting point. Each step shows the absolute path reached so far, so the final answer is produced rather than asserted. Two dots move toward the root; an ordinary name moves away from it. A longer path with more two-dot steps works exactly the same way, one step at a time.

Chaining upward

.. can be repeated. Each one moves up one more level.

From /home/engineer/project/sim/logs:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
..          →  /home/engineer/project/sim
../..       →  /home/engineer/project
../../..    →  /home/engineer
../../../.. →  /home

The reliable way to read a path full of two-dot steps is to count them, walk up that many levels from your working directory, then read the rest of the path downward. Resist doing it in your head in one jump; counting is faster than guessing and far more accurate.

What is above the root?

A fair question with a tidy answer.

The root has no parent. Rather than being an error, .. in the root points at the root itself. So this is harmless:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
/  +  ..  →  /

And it means you cannot walk out of the top of the tree by adding more two-dot steps. ../../../../../.. from anywhere eventually arrives at / and stays there.

4. These Two Are Real

Here is the fact that most introductions skip.

. and .. are not notation. They are actual entries that exist in every directory. The filesystem stores them. They are not something the shell invents and substitutes.

You can see them. ls -a shows entries that ls normally hides, and Chapter 2.6 is entirely about why they are hidden:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project

$ ls -a
.  ..  docs  rtl  scripts  sim

The first two entries in that output are the two shorthands, sitting in the listing alongside the ordinary directories. Every directory on the machine has both.

This is why .. works identically in every program, not just in Bash. A text editor, a compiler, a simulator — all of them resolve .. the same way, because they are not interpreting a shell convention. They are looking up a directory entry that is genuinely there.

5. ~ — Your Home, and It Is Different

A tilde means your home directory.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
~               →  /home/engineer
~/project       →  /home/engineer/project
~/project/rtl   →  /home/engineer/project/rtl

Convenient, and used constantly. But the mechanism is completely different from the previous two, and the difference is the point of this section.

~ is not a directory. There is no entry called ~ anywhere in the filesystem. Nothing in ls -a will ever show one.

What happens instead is Chapter 1.2's step 2. Before the command runs, Bash replaces the tilde with the text of your home directory path. By the time the program starts, there is no tilde left anywhere — the program receives /home/engineer/project and has no idea a shortcut was used.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ echo ~
/home/engineer

$ echo ~/project
/home/engineer/project

echo prints the words it is given. It printed full paths, because full paths are what it was given. The tilde was gone before echo existed.

6. The Shorthands Side by Side

WrittenMeansWho handles itReal directory entry?
/the rootthe filesystemyes
.this directorythe filesystemyes
..the parent directorythe filesystemyes
~your home directoryBash, before the command runsno

That fourth column is the one to remember. Three of these are places; one is a substitution.

7. Why ./script.sh Needs the Dot

Now the question this chapter exists to answer.

Put an executable script in a directory and try to run it by name:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ pwd
/home/engineer/project/scripts

$ ls
run.sh

$ run.sh
bash: run.sh: command not found

The file is right there. ls just listed it. And yet the shell says it cannot find a command by that name.

Read the error with Chapter 1.3's rule first: the prefix is bash:, so nothing ran. This is the shell reporting, not a program.

The explanation comes from Chapter 1.7. When you type a bare word, the shell does not treat it as a path — it treats it as a command name, and looks that name up: an alias, a function, a builtin, and then a file found by searching a list of directories.

That list does not include your current directory. So the shell searched the places it searches, did not find anything called run.sh, and reported exactly that.

The fix is to stop giving a name and start giving a path:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ./run.sh

./run.sh contains a slash. That is the signal: a word with a slash in it is a path, not a name to look up. The shell skips the whole search and goes straight to the file, resolving ./run.sh against the working directory exactly as Chapter 2.2 described.

So the dot is not magic punctuation. It is the cheapest way to turn a name into a path, because . is a real directory and adding it forces a slash into the word.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
$ ./run.sh          # a path — runs the file here
$ /home/engineer/project/scripts/run.sh   # also a path — same file
$ run.sh            # a name — searched for, not found

Why is the current directory excluded from the search? Briefly, because including it is dangerous: a file dropped into a directory you happen to be in could be run by accident simply because its name matched something you meant to type. Requiring ./ makes running a local program a deliberate act. The search list itself — what it contains and how to change it — is Module 10's subject, and it is deliberately not opened here.

8. Putting the Shorthands Together

A few realistic combinations, all resolved from /home/engineer/project/sim:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
.               →  /home/engineer/project/sim
./logs          →  /home/engineer/project/sim/logs
..              →  /home/engineer/project
../rtl          →  /home/engineer/project/rtl
../rtl/alu.sv   →  /home/engineer/project/rtl/alu.sv
../..           →  /home/engineer
../../project   →  /home/engineer/project
~               →  /home/engineer
~/project/docs  →  /home/engineer/project/docs
/etc            →  /etc

Two rows in that list are worth comparing directly.

../../project and ~/project arrive at the same place here, by different routes: one counts upward from where you are standing, the other starts from your home directory regardless of where you are. If you move somewhere else, the first changes meaning and the second does not — Chapter 2.2's distinction, now wearing shorthand.

And the last row is a reminder: /etc starts with a slash, so none of this applies. It is absolute, and your working directory is irrelevant to it.

9. Misconceptions

"~ is a directory." It is text the shell replaces. No entry named ~ exists. . and .. genuinely do exist, in every directory.

"~ means the root." It means your home directory, which is several levels below the root. This is Chapter 2.1's warning in its most common form. / is the top of the machine; ~ is your corner of it.

". and .. are the same kind of thing as ~, just shorter." They are resolved by different machinery at different times, as §5 showed.

"A single dot does nothing, so ./ is pointless." It does nothing to the meaning of a path. It does something decisive to how the shell classifies the word — §7.

"cd .. goes back to where I was." It goes up to the parent, which is often not where you came from. If you reached a directory by an absolute path from somewhere unrelated, .. has no idea about that history. Chapter 2.4 introduces cd -, which does mean "back to where I was".

"Two dots inside a path are evaluated by Bash." They are not. Bash passes them along; the filesystem resolves them when the program looks the path up. One observable consequence appears once symbolic links exist, which is Module 6.

10. Prediction Practice

Use the module's tree:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
/home/engineer/project
├── docs
├── rtl
│   ├── alu.sv
│   └── counter.sv
├── scripts
│   └── run.sh
└── sim
    └── logs

Assume the home directory is /home/engineer. Resolve each one before reading on.

Working directoryYou writeResolves to?
/home/engineer/project/rtl..?
/home/engineer/project/rtl../sim/logs?
/home/engineer/project/sim/logs../../rtl/alu.sv?
/home/engineer/project/docs./../scripts/run.sh?
/tmp~/project/rtl?
/home/engineer/project../../..?

Answers:

  1. /home/engineer/project.
  2. /home/engineer/project/sim/logs — up to project, then down two.
  3. /home/engineer/project/rtl/alu.sv — count the two-dot steps: logs → sim → project, then down into rtl.
  4. /home/engineer/project/scripts/run.sh. The leading ./ contributes nothing to the meaning; .. does the work.
  5. /home/engineer/project/rtl. The tilde was replaced by Bash first, so the working directory /tmp played no part at all.
  6. / — up to engineer, up to home, up to the root. A further .. would stay at the root, per §3.

Row 5 is the one that catches people. A path beginning with ~ becomes an absolute path before the command runs, so it behaves like /etc and not like ../rtl.

11. Check Your Understanding

Question 1. Which of ., .. and ~ exist as real entries in a directory, and which one does not? Who handles the one that does not?

Question 2. You are in /home/engineer/project/sim. Write two different paths that both name /home/engineer/project/rtl/counter.sv — one using .., one using ~.

Question 3. run.sh gives bash: run.sh: command not found, but ls shows the file. Explain in two sentences what the shell did, and give the fix.

Question 4. You run ./run.sh and get Permission denied instead of command not found. What does that change tell you about which problem you now have?

Question 5. Why does cd .. not necessarily take you back to the directory you were in a moment ago?

Question 6. From /, what does ../../.. name? Why is that not an error?

12. Remember

  • Every process has one working directory, always an absolute path. Your shell has one; a program it starts gets a copy and cannot change yours.
  • . is this directory and .. is the parent — and both are real entries that every directory contains. ls -a shows them.
  • Count the two-dot steps, walk up that many levels, then read the rest downward. That method does not fail; guessing does.
  • .. in the root points at the root, so you cannot walk off the top of the tree.
  • ~ is not a directory. Bash replaces it with your home path before the command runs, which is why a tilde path behaves like an absolute one.
  • A word containing a slash is a path; a bare word is a command name. The current directory is not in the list of places searched for command names.
  • ./run.sh exists to add that slash — it turns a name into a path. Whether the file then runs is a permissions question, and a different error message.
  • command not found and Permission denied are different stages. The first means the file was never located; the second means it was.

You can now write any path you need. The next chapter picks up the three commands that let you move through the tree and confirm, every time, that you landed where you intended.

Where this fits

Part of the Linux & Bash curriculum.