How are the above . & .. used in the shell command line?
In many ways depending on context. Simple illustrations:
- For path resolution with the builtin
cd
command for example like you said
Literally
, inside a pattern, for instance in the context of pathname expansion
- In a
pattern
to replace any single one character with a command like grep
Consider man cd
, man path_resolution
and this explanation on how the builtin cd
command works internally (man cd
here):
(4). If the first component of the directory operand is dot or dot-dot, proceed to step 6.
(6). Set curpath to the string formed by the concatenation of the
value of PWD, a slash character, and the operand.
(8). The curpath value shall then be converted to canonical form as
follows, considering each component from beginning to end, in
sequence:
a. Dot components and any slashes that separate them from the next
component shall be deleted.
b. For each dot-dot component, if there is a preceding component
and it is neither root nor dot-dot, the preceding component, all
slashes separating the preceding component from dot-dot, dot-dot and
all slashes separating dot-dot from the following component shall be
deleted.
...
and this, which is a step-by-step example of how the steps above seemingly apply to changing directory from /home/user
to ../../boot/memtest86
:
# echo $PWD
/home/user
(4). cd ../../boot/memtest86
(6). curpath = /home/user/../../boot/memtest86
(8)b
/home/user/../../boot/memtest86
/home/../boot/memtest86 //step 1
/ boot/memtest86 //step 2
curpath = /boot/memtest86 //result
By trimming dot components to the same extent as the working directory depth, inevitably this yields a path expressed from the root. The steps for a single dot case etc. were skipped since it concatenates like above, then removes ./
which is very easy to imagine as we're in the current directory. So this illustrates how .
and ..
referencing the current and parent directory is implemented in this command's context internally, which is not through "substitution" but rather something akin to stream editing...
You can investigate pathname expansion and pattern matching in bash
After word splitting, unless the -f option has been set (see The Set
Builtin), Bash scans each word for the characters *, ?, and [...]
If one of these characters appears, then the word is regarded as a
pattern, and replaced with an alphabetically sorted list of file names
matching the pattern. ...
In a pattern for a pathname like this, any character other than *
,?
and [...]
matches itself. So this means a dot can match itself literally:
ls .*
...will expand to ..
,.
(because * includes also null) and accordingly will list current and parent directory and also any file or directory in the current directory which literally starts with a dot (.*) and is followed by something else of whatever length. As explained in the manual you have some level of control over the expansion behavior etc. (using *glob options to set
and shopt
).
Here is an example of the character being used in a pattern (as it's grep pattern file
1) to select any one character, and is of course unrelated to file or directory names:
ls -la | grep .
This prints the directory contents so it catches everything (grep -v .
is used to catch empty lines). Generally with patterns in such expressions and most certainly that is the case with grep
, a single dot matches any single character. Finally consider these special characters examples in the dot .
section for a quick reminder of some of the different use cases.
So a dot can be used in path resolution, as a literal character which is part of a pattern, it can replace a single character in an expression with grep
and it can be even be a bash builtin used to execute commands from a file etc. How it is used on the command line varies with context...
1. This is of course about the syntax of a specific command. If a command accepts a file/path as an argument then using the dot in its stead, as others have shown, expands to the current working directory which is quite convenient.
Thats three questions in one ;-)
AUTO_CD Option and howto find it
First of all the option you are looking for is AUTO_CD.
You can easily find it by looking up man zshoptions
. Use your pagers search function, usually you press / and enter the keyword. With n you jump to the next occurrence. This will bring up the following:
[..]
Changing Directories
AUTO_CD (-J)
If a command is issued that can't be executed as a normal command, and the command is the name of a directory, perform the cd command to that directory.
[..]
The option can be unset using unsetopt AUTO_CD
.
Turning it properly off
You are using oh-my-zsh which is described as
"A community-driven framework for managing your zsh configuration"
Includes 120+ optional plugins (rails, git, OSX, hub, capistrano, brew, ant, macports, etc), ...
So the next thing is to find out, how to enable/disable options according to the framework.
The readme.textile file states that the prefered way to enable/disable plugins would be an entry in your .zshrc: plugins=(git osx ruby)
Find out which plugin uses the AUTO_CD option. As discovered from the manpage it can be invoked via the -J switch or AUTO_CD. Since oh-my-zsh is available on github, searching for it will turn up the file lib/theme-and-appearance.zsh
.
If you don't want to disable the whole plugin "theme-and-appearance", put a unsetopt AUTO_CD
in your .zshrc. Don't modify the files of oh-my-zsh directly, because in case you are updating the framework, your changes will be lost.
Why executables are not invoked directly
Your third question is howto execute a binary directly:
You have to execute your binary file via a path, for example with a prefixed ./
as in ./do-something
. This is some kind of a security feature and should not be changed.
hing of plugging in an USB stick, mounting it and having a look on it with ls
. If there is a executable called ls
which deletes your home directory, everything would be gone, since this would have overwritten the order of your $PATH.
If you have commands you call repeatedly, setting up an alias in your .zshrc would be a common solution.
Best Answer
When you run the command
the shell looks up the file
hello2
in the directory.
, i.e. in the current directory. It then runs the script or binary according to some rules (which are uninteresting in this context).The command
also causes the shell to execute the file.
This is because
.
and./.
is the same directory.Every directory has a
.
directory entry. This entry corresponds to the directory itself. So saying./
is the same as saying././
and././././
etc.The only difference is that the system might have to do a few extra directory lookups (unless the shell is smart and spots the obvious simplification).
Every directory also has a
..
entry which points to its parent directory.This means that if the current directory is called
alamin
, then the following would also execute the file:as would
and
The root directory,
/
, is a special case. Its..
directory entry is the same as its.
directory entry. This means that you can't go "above" it with/..
.See also: The number of links for a folder doesn't reflect the real status?