In system calls that take file paths as arguments, .
is a relative path that refers to here, and ..
to the parent directory. some/dir/.
is the same as some/dir
¹, some/dir/..
is the parent directory of some/dir
, possibly some
if some/dir
is not a symlink.
Traditionally, .
and ..
were implemented as hard links, .
to the directory it's in, ..
to its parent, initially by the mkdir
utility and later by the mkdir()
system call. Depending on the filesystem, it may or may not still be the case. Those .
and ..
may or may not be returned by readdir()
/ getdents()
, but regardless, they are always required to resolve to here and the parent directory in system calls that take file paths as arguments.
As a consequence, that applies as well to most commands that take file paths as arguments:
vi some/dir/../file
edits the file
file in the parent directory of some/dir
(not necessarily the same as some/file
).
ls
is short for ls .
which lists the contents of the current working directory. ls -ld
short for ls -ld .
which lists details of the current working directory file.
ls -l ..
lists the contents of the parent directory of the current working directory.
cd
(and pushd
in those shells that have it) is an exception in most shells though, as cd
implements its own logical directory traversal.
cd some/dir/..
doesn't do a chdir("some/dir/..")
(where chdir()
is the actual system call to change the current working directory), but chdir("some")
or in some shells chdir("$PWD/some")
(sometimes, even if $PWD
is no longer a path to the current working directory). And cd ..
is not doing chdir("..")
but something like chdir(dirname($PWD))
.
That is, cd
(and cd
only) treats ..
specially by itself in order to treat symlinks as if they were directories, in order to try and minimise the risk
of surprises to the user. For instance, cd some/dir; cd ../..
should get you back to where you were initially even if some/dir
or some
happens to be a symlink to /somewhere/entirely/different
.
It's important to bear in mind as it can cause some confusion. vi some/dir/../file
may edit a different file from cd some/dir/.. && vi file
for instance.
For cd
to treat ..
the same as other commands, you need the -P
option². And that's why it's often recommended to use cd -P
in scripts (so a program written in shell works the same as one written in any other language in that regard).
Now, ...
is not special, so it's treated as any other file.
mkdir ... && cd ...
will create a directory called ...
(hidden as it starts with a .
) and chdir()
into it (as chdir("...")
or chdir("$PWD/...")
depending on the shell).
cd ...
would return an error that ...
doesn't exists if it doesn't like cd any/other/inexistent/directory
.
cd...
without whitespace between cd
and ...
would try to call the cd...
command, which likely doesn't exist in your environment and return an error accordingly.
Now, to shorten typing, some people create an alias for cd...
as:
alias cd...='cd ../..' cd....='cd ../../..'
So calling cd...
would cd
to the parent directory of the parent directory of the current working directory (logically, as in it would take two directory components off the tail of $PWD
, not do a chdir("../..")
as seen above).
zsh
also has global aliases which are expanded anywhere, not only in command position like regular aliases, so some people have been known to do:
alias -g ...=../.. ....=../../..
Which means that cd ...
and ls ...
get changed to cd ../..
or ls ../..
before being executed. That doesn't apply to cd .../dir
though. There are better ways to achieve something similar using custom bindings to the . key.
¹ though if some/dir
is a symlink, some/dir/.
, like some/dir/
would refer to the directory the symlink points to, a distinction that matters for system calls that apply prior to symlink resolution such as lstat()
, lchown()
, readlink()
, unlink()
and not after (like open()
, chown()
...).
² well, -P
doesn't prevent the $CDPATH
/$cdpath
handling nor the special treatment of -
(or -1
, +2
... in zsh), but that's a separate issue.
.
is the current directory,..
the parent directory, and there is no...
– muru Sep 25 '23 at 04:38...
you might be looking for../..
to go (at most) 2 directories up. – Aeronautix Sep 25 '23 at 05:11..
has a different meaning forcd
/pushd
from anywhere else (though my answer covers it there), and here we'd need to cover the commonly usedalias 'cd...=cd ../..
andalias -g ...=../..
. – Stéphane Chazelas Sep 25 '23 at 07:20...
, so in the parent of that, there actually is a...
, but in general @muru is right. – Henrik supports the community Sep 25 '23 at 15:30