Pull to refresh

Улучшаем работу в консоли или как я написал команду sshcdvim

Reading time3 min
Views13K
Наверняка многие делали так, как на картинке, но вот только у них при этом выдалась ошибка типа «файл не найден». Давайте исправим эту проблему, чтобы при таких очевидных опечатках происходило именно то, что вы хотели. То есть, когда вы пишете «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 можно поменять проверки местами, если необходимо.

Воспользовавшись такой магией баша, вы сможете удивлять коллег по работе и даже показывать фокусы по телевизору! Надеюсь, вам понравилась статья и она окажется полезной для вашей повседневной работы.
Tags:
Hubs:
0
Comments17

Articles