Вы не можете иметь псевдоним с пробелами. Чтобы сделать то, что вы хотите с псевдонимами, вам нужно воспользоваться этим свойством:
Если значение псевдонима, заменяющего слово, заканчивается на <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