You cannot have an alias name with spaces. To do what you want with aliases you need to take advantage of this property:
If the value of the alias replacing the word ends in a <blank>, the shell shall check the next command word for alias substitution; this process shall continue until a word is found that is not a valid alias or an alias value does not end in a <blank>.
(source), so cd
and consecutive ...
are resolved as aliases.
You need aliases like this:
cd='cd '
...='../..'
....='../../..'
# and so on
But then if you happen to have a directory named ls
and you type cd ls
, then ls
will also be prone to alias substitution. If ls
is an alias, this will backfire.
Pure alias approach is therefore wrong. This function will do (use it without the above aliases):
cd() {
if [ "$#" -eq 0 ]; then
command cd
elif [ "$(printf '%s' "$1" | wc -l)" -eq 0 ]; then
command cd "$(printf '%s' "$1" | sed '/^\.\.\+$/ {s|..|.|; s|.|../|g }')";
else
command cd "$1"
fi
}
(Note: to make it work in zsh
, invoke set -o POSIX_BUILTINS
or replace every command
with builtin
in the function body).
sed
gets the argument passed to the function and changes it iff it consists of two or more dots; the tool removes the first dot and replaces every dot (that's left) with ../
.
There is additional logic:
[ "$#" -eq 0 ]
allows the sole cd
(without arguments) to work as it should.
[ "$(printf '%s' "$1" | wc -l)" -eq 0 ]
is to prevent sed
to alter multi-line directory names (e.g. foo<newline>.....
which is a valid name). Note that for usual names (not containing newlines) wc -l
returns 0
(not 1
, POSIX doesn't consider a "line" without terminating newline to be a line), hence we test against 0
.
And there's a quirk:
- In
s|..|.|
the first two dots are not literal dots, this is regex. One may say it should be s|\.\.|.|
but notice /^\.\.\+$/
ensures there are only dots in the line in the first place. The same applies to the first dot in s|.|../|g
.
This actually works quite nicely. I'm not sure how or why, but this works for
cd ..
,cd ...
,cd ....
, andcd .....
(I haven't tried for more than 5 dots, but this is all I need :-D ) – Jimmy Huch – 2019-01-23T16:27:01.697I'm confused. On my system (MacOs Mojave, bash version 3.2.57), only
cd ...
works. With 4 dots I get, as expected, the error message-bash: cd: ../...: No such file or directory
– Hartmut Braun – 2019-01-23T17:35:50.543