Вы не можете иметь псевдоним с пробелами. Чтобы сделать то, что вы хотите с псевдонимами, вам нужно воспользоваться этим свойством:
Если значение псевдонима, заменяющего слово, заканчивается на <blank>, оболочка должна проверить следующее командное слово на предмет замены псевдонима; этот процесс будет продолжаться до тех пор, пока не будет найдено слово, которое не является допустимым псевдонимом или значение псевдонима не заканчивается на <blank>.
(источник), поэтому cd
и последовательные ...
разрешены как псевдонимы.
Вам нужны такие псевдонимы:
cd='cd '
...='../..'
....='../../..'
# and so on
Но если у вас есть каталог с именем ls
и вы cd ls
, то ls
также будет подвержен подстановке псевдонимов. Если ls
является псевдонимом, это будет иметь неприятные последствия.
Следовательно, подход чистого псевдонима неверен. Эта функция будет делать (используйте ее без вышеуказанных псевдонимов):
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
}
(Примечание: чтобы заставить его работать в zsh
, вызовите set -o POSIX_BUILTINS
или замените каждую command
на builtin
в теле функции).
sed
получает аргумент, переданный функции, и меняет его, если он состоит из двух или более точек; инструмент удаляет первую точку и заменяет каждую оставшуюся точку на ../
.
Есть дополнительная логика:
[ "$#" -eq 0 ]
позволяет единственному cd
(без аргументов) работать как надо.
[ "$(printf '%s' "$1" | wc -l)" -eq 0 ]
запрещает sed
изменять имена многострочных каталогов (например, foo<newline>.....
которое является допустимым именем) , Обратите внимание, что для обычных имен (не содержащих символов новой строки) wc -l
возвращает 0
(не 1
, POSIX не считает "строку" без завершения новой строки строкой), поэтому мы проверяем значение 0
.
И есть странность:
- В
s|..|.|
первые две точки не являются буквальными точками, это регулярное выражение. Можно сказать, что это должно быть s|\.\.|.|
но обратите внимание /^\.\.\+$/
гарантирует, что в строке есть только точки. То же самое относится и к первой точке в s|.|../|g