When should I use the ~ (tilde) during command line navigation?
Pretty stupid when it comes to linux and I'm trying to figure out navigation with the command line. I can move back and forth from my home folder and the folders inside pretty easily with this:
cd ~/Documents/
but when I go to open a folder in documents i'm getting an error like this:
chance@asus:~/Documents$ cd ~/xmr-stak-cpu-1.3.0-1.5.0
bash: cd: /home/chance/xmr-stak-cpu-1.3.0-1.5.0: No such file or directory
I'm confused because I need to use "~" to get into documents, but I cannot navigate into a subsequent folder while in documents.
Solution 1:
TL;DR
- path is read left to right, with leftmost directory specified being the top of the directory tree you're traversing
- leading
~/
in path means your home folder - leading
./
means in this folder or stuff in current working directory - navigating to a directory can be done via giving path relative to your current working directory, or specifying full path
-
~
is relevant in command-line only, not in GUI (as mentioned in comments).
The answer is edited to include more formal explanation of tilde expansion and to suit the new edited title of the question, so please read the more formal explanation below. First two sections are more or less gentle explanations of what OP did and didn't do.
The problem
The leading ~
(tilde) followed by slash in path is understood as reference to your user's home directory, i.e. ~/Documents
always means /home/chance/Documents
. (There are exceptions and special cases but for the purpose of explaining the basics, let's keep it simple so far; see below for the deeper explanation).
So when you do cd ~/xmr-stak-cpu-1.3.0-1.5.0
, you're saying take me to xmr-stak-cpu-1.3.0-1.5.0
directory that is located in my home folder. What also is important to note, is that a path is always read left to right, separated by slashes, with the leftmost being the top of the directory tree that you reference. So if you want to descend from home, to Documents, to your folder, all pieces must be present in the path, separated by slashes, and the folder you want to end up in, of course, has to be the right most.
Look at the error message closely:
bash: cd: **/home/chance/xmr-stak-cpu-1.3.0-1.5.0**: No such file or directory
The shell properly expanded ~
to be /home/chance
and joined that with what you gave it. Of course, because the directory you specified doesn't exist, you got the appropriate error message.
What you should have done
You can do it in one of two ways - give full path or jump into ~/Documents
first, then jump to directory you want. When you cd ~/Documents
and want to navigate to folder that's located inside the current directory that you're at, you can use ./
notation. So you would do:
$ cd ~/Documents
$ cd ./xmr-stak-cpu-1.3.0-1.5.0/
Of course you don't have to add that ./
, when you simply do cd xmr-stak-cpu-1.3.0-1.5.0
will automatically look inside your current working directory. However, it's better to be explicit, and besides ./
helps avoiding issues with filenames that might start with -
(which is a whole different bag of problems and is a topic for another day).
Alternatively, you can give full path:
$ cd ~/Documents/xmr-stak-cpu-1.3.0-1.5.0/
Note that you can also use the $HOME
variable instead of ~
, which is pretty much the same in effect, however they differ in nature and in the extra stuff that you can do with ~
. See my answer on Difference cd and cd ~.
More formal and in-depth explanation
Alright, so far we've kept things fairly simple for the purpose of explaining basics to new users. But there's much more to tilde, dot-slash, and navigating the directory tree than that. Matters get more complicated when we consider that tilde and cd
behave differently in other shells, and if we also consider the POSIX standard. Some of the things here I've already touched on in my related answer on Unix & Linux, so be sure to check that out as well.
In Bourne-like shells (that is bash
, ksh
, ksh
-related implementations like mksh
, and Ubuntu's default /bin/sh
, which is actually dash
) the unquoted leading tilde signifies Tilde Expansion, which is in fact specified as standard behavior by POSIX. Depending on what follows an unquoted leading tilde, it has different effects:
-
with an unquoted leading
~
, when there are no characters following it (or if there's nothing between~
and next unquoted/
, i.e. a null string) it expands to the same value as$HOME
environment variable, i.e. your home folder. Socd ~
andcd ~/
mean change directory to your home folder. Note that~
and/
should be unquoted:$ bash -c 'cd /etc/; ls -d ~' /home/xieerqi $ bash -c 'cd /etc/; ls -d ~/' /home/xieerqi/ $ bash -c 'cd /etc/; ls -d ~"/"' ls: cannot access '~/': No such file or directory $ bash -c 'cd /etc/; ls -d "~"/' ls: cannot access '~/': No such file or directory
-
with an unquoted leading
~
, the collection of characters that follow it are considered a possible login name. Socd ~testuser
orcd ~testuser/
would mean you want to jump intotestuser
's current working directory. Again, quoting matters:$ bash -c 'cd /etc/; ls -d ~testuser' /home/testuser $ bash -c 'cd /etc/; ls -d ~"testuser"' ls: cannot access '~testuser': No such file or directory $ bash -c 'cd /etc/; ls -d ~testuser"/"' ls: cannot access '~testuser/': No such file or directory
This is all standard behavior and works across the board in dash
, ksh
, and of course bash
. However, there are a few things that shells do differently. In particular, bash
has extra expansions that you can perform with tilde, and handles an unset HOME
differently than other shells. Here are the extra expansions you can do in bash
:
-
~+
references your current working directory, same asPWD
variable. This also works inksh
but notdash
.$ bash -c 'echo ~+; unset PWD;echo ~+' /home/xieerqi ~+
-
~-
references your previous working directory, same asOLDPWD
variable. Also works inksh
but notdash
.$ bash -c 'cd /etc/;cd /usr; echo ~-; unset OLDPWD;echo ~-' /etc ~-
-
In
bash
you can navigate AND record where you've been by pushing specific directories on the directory stack (or array), and you can reference them by~[+-]<NUMBER>
, where+
would mean looking from the left of the array, and-
from the right. This isbash
specific and doesn't work work inksh
nordash
.$ bash -c 'pushd /etc/; pushd /usr; echo ~+1' /etc ~ /usr /etc ~ /etc
See diagram in muru's answer to a related question, which shows how to use indexes for
~+
and~-
.
Another thing that I've already hinted at is the unset HOME
environment variable. The fact that it is a variable and can be unset poses a problem - as specified by POSIX standard, tilde expansion depends on the environment variables, but according to the standard "[i] HOME is unset, the results are unspecified." In this case, ksh
and dash
simply break:
$ ksh -c 'cd /usr; unset HOME; cd ~'
ksh: cd: xieerqi: [No such file or directory]
$ dash -c 'cd /usr; unset HOME; cd ~'
dash: 1: cd: can't cd to ~
In fact, this is in accordance with the standard for cd
as well:
- If no directory operand is given and the HOME environment variable is empty or undefined, the default behavior is implementation-defined and no further steps shall be taken.
By contrast bash
, handles things differently. According to the bash manual:
If HOME is unset, the home directory of the user executing the shell is substituted instead. Otherwise, the tilde-prefix is replaced with the home directory associated with the specified login name.
In other words, when home is unset only, bash won't break, but if HOME
is set to the null string, it will break:
$ bash -c 'cd /etc; unset HOME; cd ~; pwd'
/home/xieerqi
$ bash -c 'cd /etc; HOME=""; cd ~; pwd'
/etc
Fun fact
~
was chosen to represent user's home directory because one upon a time ~
and HOME
keys used to reside on the same keyboard key on Lier-Siegler ADM-3A terminal. (source)
See also:
- Commandline shortcut for current directory similar to ~ for home directory?
- Is the tilde,
~
considered to be a relative path? - How does using the tilde work as a shortcut to my home directory?
Solution 2:
The tilde (~
) is short for your home directory (like the environment variable $HOME
). You can run echo ~
to see for yourself. In your case, you will see /home/chance
.
The absolute path1 of the directory you want to access is ~/Documents/xmr-stak-cpu-1.3.0-1.5.0
, so if you want, you can cd
straight there, and this will work regardless of where you are:
cd ~/Documents/xmr-stak-cpu-1.3.0-1.5.0
If you're already in ~/Documents
, you can use the relative path1:
cd xmr-stak-cpu-1.3.0-1.5.0
Or, more verbose, you can use ./
to refer to the current directory:
cd ./xmr-stak-cpu-1.3.0-1.5.0
Also note that if you're currently in ~
, there is a different relative path:
cd Documents/xmr-stak-cpu-1.3.0-1.5.0
Footnotes:
-
From Wikipedia, absolute paths vs relative paths:
An absolute or full path points to the same location in a file system, regardless of the current working directory. To do that, it must include the root directory.
By contrast, a relative path starts from some given working directory, avoiding the need to provide the full absolute path.