Наверняка многие делали так, как на картинке, но вот только у них при этом выдалась ошибка типа «файл не найден». Давайте исправим эту проблему, чтобы при таких очевидных опечатках происходило именно то, что вы хотели. То есть, когда вы пишете «ssh <dirname>», происходил заход в директорию <dirname> и наоборот, когда вы делаете «cd <hostname>» происходит заход по ssh. Ну и заодно сделаем то же самое для vim, чтобы 2 раза не вставать.
Скрипты с #!/bin/sh в начале под названием ssh/cd/vim
Если мы попробуем пойти наивным путем и просто написать скрипты под названием «ssh», «cd» и «vim», то реально запускать ни vim, ни ssh у нас не получится из-за бесконечной рекурсии:
#!/bin/sh
# нужно назвать файл ssh, cd или vim и поместить скрипт в $PATH перед настоящими утилитами,
# например в директорию /bin, которая почти всегда идет перед /usr/bin, в которой как правило лежат vim и ssh
# проверим сначала, не является ли первый аргумент ($1) директорией ([ -d ... ] означает проверку на директорию, см. man test для деталей)
if [ -d "$1" ]; then
cd "$1"
# иначе, если это файл (-f), то запустим vim
elif [ -f "$1" ]; then
vim "$1"
# поскольку определить, что это hostname сложнее всего, будем считать, что первый аргумент это hostname, если это не файл и не директория
else
ssh "$1"
fi
Такой подход будет работать для команд vim и ssh, если назвать скрипт как-то по-другому, чтобы мы не обращались сами к себе, или если прописать полные пути до vim и ssh (тогда это будет непортируемо, поскольку в разных системах эти утилиты могут жить в разных директориях).
Однако, для команды cd такое работать не будет от слова «совсем», к сожалению, поскольку cd является встроенной командой в bash. То есть, не будет работать ни «cd localhost», ни «ssh <dirname>».
Также, мы всегда смотрим только на первый аргумент ($1), и передача дополнительных флагов не будет работать. Например, нельзя будет выполнить команду «ssh localhost uptime» и вместо этого мы просто зайдем по ssh на localhost.
Улучшенный скрипт
Давайте попробуем решить хотя бы проблему с тем, что мы не передаем аргументы команде. Для этого существует очень забавная конструкция "$@", которая служит для передачи списка аргументов в команды «как есть», с учетом экранирования. Это отличается от "$*", которая склеит все аргументы в один, и также отличается от $* (без кавычек), которая превратит аргументы с пробельными символами в разные аргументы.
Итак, улучшенный вариант скрипта:
#!/bin/sh
if [ -d "$1" ]; then
echo 'Пожалуйста, смените сами директорию на следующее: cd ' "$@"
elif [ -f "$1" ]; then
vim "$@"
else
ssh "$@"
fi
Теперь команда «vim localhost uptime» будет работать, если вы поместили этот скрипт в /bin/vim. Но все остальные проблемы останутся, к сожалению. Проблему с cd внутри скрипта мы решили с помощью вызова echo, но всё же хотелось получить решение получше, чтобы директория при этом менялась и нам не приходилось самим набирать команду cd.
Алиасы в bash
Лично я знаю 2 способа подменить встроенные команды в bash: алиасы и функции. Однако, возможности алиасов сильно ограничены и им недоступны аргументы, которые передаются в функцию:
$ alias cd='echo ALL YOUR BASH ARE BELONG TO US; cd'
$ cd <some_dir>
ALL YOUR BASH ARE BELONG TO US
<some_dir>$
Алиасы в баше работают весьма просто и внутри других алиасов не разворачиваются. В данном случае вышеприведенный пример — это почти всё, что можно сделать с помощью алиасов в баше.
Функция sshcdvim
Поскольку у нас почти не остается выбора, давайте напишем функцию. Она будет выглядеть следующим образом:
function sshcdvim() {
if [ -d "$1" ]; then
cd "$@"
elif [ -f "$1" ]; then
vim "$@"
else
ssh "$@"
fi
}
Этот код нужно поместить в ".bashrc" и перезапустить bash. Теперь вы можете пользоваться функцией sshcdvim, которая сама выберет, что запускать.
Однако, если вы захотите назвать свою функцию cd, vim или ssh, то опять получите бесконечную рекурсию при попытке использования.
Понятия builtin и command в bash
Чтобы объявленные функции в bash не влияли на исполнение скриптов, существуют 2 ключевых слова в bash: builtin и command.
Ключевое слово builtin перед именем команды указывает интерпретатору, что не нужно запускать функцию или команду, а нужно запустить встроенную команду. В нашем случае такой встроенной командой является cd.
Ключевое слово command делает то же самое, что и builtin, но используется для настоящих команд. В нашем случае настоящими командами являются vim и ssh, поэтому их и нужно использовать.
Конечный вариант будет выглядеть так:
function ssh() {
if [ -d "$1" ]; then
builtin cd "$@"
elif [ -f "$1" ]; then
command vim "$@"
else
command ssh "$@"
fi
}
Для команд vim и cd можно поменять проверки местами, если необходимо.
Воспользовавшись такой магией баша, вы сможете удивлять коллег по работе и даже показывать фокусы по телевизору! Надеюсь, вам понравилась статья и она окажется полезной для вашей повседневной работы.
Автор: youROCK