Как я могу сделать свои собственные «команды оболочки» (например, mkdir /cd combo)?

Я не могу сказать, сколько раз я хотел, чтобы команда создавала каталог и переходила в этот каталог. В принципе, я хотел бы получить эквивалент следующего:

mkdir -p /arbitrarily/long/path; cd /arbitrarily/long/path

, но только для ввода кода /arbitrarily/long/path, например:

mk-cd /arbitrarily/long/path

Я попытался создать сценарий для этого, но он меняет только каталог внутри скрипта. Мне также хотелось бы изменить каталог в оболочке.

#!/bin/bash
mkdir $1
cd $1
export PWD=$PWD

Как я могу сделать эту работу?

41 голос | спросил Christopher Bottoms 6 Maypm16 2016, 16:09:18

4 ответа


92

Самый простой способ - использовать функцию оболочки:

mkcd() {
    mkdir -p -- "$1" && cd -- "$1"
}

Поместите его в свой .bashrc файл, чтобы он был доступен вам как другая команда оболочки.

Причина, по которой он не работает как внешний скрипт, - это cd изменяет текущий каталог исполняемого скрипта, но не влияют на вызывающий. Это по дизайну! Каждый процесс имеет свой собственный рабочий каталог, который наследуется его дочерними элементами, но противоположное невозможно.

Если часть конвейера не выполняется в фоновом режиме или явно в подоболочке, функция оболочки не запускается в отдельном процессе, а в том же самом, как если бы команда была получена. Затем текущую оболочку каталога можно изменить с помощью функции.

&&, используемый здесь для разделения обеих используемых команд, означает, что первая команда завершается успешно (mkdir), запустите второй (cd). Следовательно, если mkdir не удается создать запрошенный каталог, нет смысла пытаться в него входить. Сообщение об ошибке печатается с помощью mkdir и все.

Параметр -p, используемый с mkdir, чтобы сообщить этой утилите о создании любого отсутствующего каталога, который является частью полного пути имени каталога, переданного как аргумент. Одним из побочных эффектов является то, что если вы попросите создать уже существующий каталог, функция mkcd не будет терпеть неудачу, и вы попадете в этот каталог. Это может считаться проблемой или функцией. В первом случае функция может быть изменена, например, таким образом, которая просто предупреждает пользователя:

mkcd() {
    if [ -d "$1" ]; then
        printf "mkcd: warning, \"%s\" already exists\n" "$1"
    else
        mkdir -p "$1" 
    fi && cd "$1"
}

Без опции -p поведение исходной функции было бы совсем другим.

Если каталог, содержащий созданный каталог, еще не существует, mkdir не работает так же, как и функция.

Если создаваемый каталог уже существует, сбой mkdir и cd не вызывается.

Наконец, обратите внимание, что установка /экспорт PWD бессмысленна, поскольку оболочка уже делает это внутри.

Изменить: я добавил параметр -- для обеих команд, чтобы функция разрешила имя каталога, начиная с тире.

ответил jlliagre 6 Maypm16 2016, 16:20:47
32

Я хотел бы добавить альтернативное решение.

Ваш скрипт будет работать, если вы вызываете его с помощью . или source:

. mk-cd /arbitrarily/long/path

Если вы сделаете это,

export

Причина этого заключается в том, что скрипт обычно работает в суб-оболочке, поэтому его среда теряется при завершении, но . (или alias) заставляет его запускаться в текущей оболочке.

Этот метод может быть полезен для командных последовательностей, которые слишком сложны для функции или находятся в разработке и часто редактируются: после alias mk-cd='. mk-cd' был введен в ., вы можете редактировать сценарий по своему усмотрению без повторной инициализации.

Обратите внимание на следующее: -

Если вы пишете скрипт, который должен вызываться с помощью source /alias, есть два способа убедиться в этом: -

  1. По какой-то причине скрипт, вызываемый с помощью .bash_aliases /. не обязательно быть исполняемым, поэтому просто удалите это разрешение, и сценарий либо не будет найден в «$ PATH», либо даст ошибку разрешения при вызове с явным путем.

  2. В качестве альтернативы во главе скрипта можно использовать следующий трюк:

source

Это работает, потому что в суб-оболочке . выдается предупреждение, хотя нет статуса ошибки: следовательно source используется для выдачи ошибки без ввода.

ответил AFH 6 Maypm16 2016, 17:38:25
13

Не одна команда, но вам не нужно повторно указывать весь путь, просто используйте !$ (который является последним аргументом из предыдущая команда в истории оболочки).

Пример:

mkdir -p /arbitrarily/long/path
cd !$
ответил RiaD 8 Maypm16 2016, 21:05:45
1

Создав псевдонимы . Очень популярный способ создания собственных команд.

Вы можете создать псевдоним «на лету»:

alias myalias='mkdir -p /arbitrarily/long/path; cd /arbitrarily/long/path'

Вот и все. Если вы хотите сохранить этот псевдоним на постоянной основе (а не только текущий сеанс), тогда поместите эту команду в dotfile (обычно ~ /.bash_aliases или ~ /.bash_profile).

ответил James 7 Maypm16 2016, 19:53:55

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132