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