it-swarm-ru.tech

Существует ли однострочник, позволяющий мне создавать каталог и одновременно перемещаться в него?

Я повторяю много:

mkdir longtitleproject
cd longtitleproject

Есть ли способ сделать это в одной строке, не повторяя имя каталога? Я здесь на башке.

166
methodofaction

Встроенной команды нет, но вы можете легко написать функцию, которая вызывает mkdir затем cd:

mkcd () {
  mkdir "$1"
  cd "$1"
}

Поместите этот код в ваш ~/.bashrc файл (или ~/.kshrc для пользователей ksh или ~/.zshrc для пользователей zsh). Он определяет функцию с именем mkcd. "$1" будет заменен аргументом функции при запуске.

Эта простая версия имеет несколько недостатков:

  • Вы не можете создать цепочку подкаталогов сразу. Исправить: передать -p опция mkdir. (Это может быть или не быть желательным, так как это увеличивает риск того, что опечатка останется незамеченной, например mkcd mydierctory/newsub с радостью создаст mydierctory и ​​mydierctory/newsub когда вы намеревались создать newsub внутри существующего mydirectory.)
  • Если аргумент начинается с - но не просто -, тогда mkdir и ​​cd интерпретируют его как опцию. Если это просто -, тогда cd будет интерпретировать его как значение $OLDPWD. Если это + с последующим 0 или более цифрами, тогда cd в zsh будет интерпретировать его как индекс в стеке каталогов. Вы можете исправить первую проблему, но не две другие, передав -- до ссоры. Вы можете исправить все эти проблемы, добавив ./ к аргументу, если это относительный путь.
  • mkdir не следует за CDPATH, но cd делает, поэтому, если вы установили для CDPATH значение, которое не начинается с . (предположительно несколько необычная конфигурация), тогда cd может привести вас к другому каталогу, чем тот, который был только что создан. Предшествующий ./ к относительным путям исправляет это (это приводит к игнорированию CDPATH).
  • Если mkdir терпит неудачу, он пытается выполнить cd. Исправить: использовать &&, чтобы разделить две команды.

Все еще довольно просто:

mkcd () {
  case "$1" in /*) :;; *) set -- "./$1";; esac
  mkdir -p "$1" && cd "$1"
}

Эта версия все еще может заставить cd перейти в каталог, отличный от того, который mkdir только что создал в одном случае Edge: если аргумент mkcd содержит .. и ​​проходит по символической ссылке. Например, если текущим каталогом является /tmp/here и ​​mylink является символической ссылкой на /somewhere/else, тогда mkdir mylink/../foo создает /somewhere/else/foo в то время как cd mylink/../foo изменяется на foo. Недостаточно искать символические ссылки в аргументе, поскольку оболочка также отслеживает символические ссылки в своем текущем каталоге, поэтому cd /tmp/mylink; mkdir ../foo; cd ../foo не изменяется в новый каталог (/somewhere/else/foo) но в /tmp/foo. Исправление для этого - позволить встроенной функции cd разрешить все .. сначала компоненты пути (не имеет смысла использовать foo/.. если foo не существует, поэтому mkdir никогда не нужно видеть ..).

Мы приходим к этой надежной, хотя и немного кровавой версии:

mkcd () {
  case "$1" in
    */..|*/../) cd -- "$1";; # that doesn't make any sense unless the directory already exists
    /*/../*) (cd "${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd -- "$1";;
    /*) mkdir -p "$1" && cd "$1";;
    */../*) (cd "./${1%/../*}/.." && mkdir -p "./${1##*/../}") && cd "./$1";;
    ../*) (cd .. && mkdir -p "${1#.}") && cd "$1";;
    *) mkdir -p "./$1" && cd "./$1";;
  esac
}

(Упражнение: почему я использую подоболочку для первого вызова cd?)

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


Есть также менее специализированные способы не перепечатывать Word из предыдущей строки:

  • Введите cd, затем Esc. (или Alt+.) вставить последний аргумент из предыдущей команды.
  • cd !$ выполняет cd для последнего аргумента предыдущей команды.
  • Нажмите Up чтобы вызвать предыдущую командную строку, затем отредактируйте ее, чтобы изменить mkdir на cd.
172
Gilles 'SO- stop being evil'

Это тот вкладыш, который вам нужен. Никаких других настроек не требуется:

mkdir longtitleproject && cd $_

$_ переменная, в bash, это последний аргумент, переданный предыдущей команде. В этом случае имя каталога, который вы только что создали. Как объяснено в man bash:

_         At  Shell  startup,  set to the absolute pathname used to invoke
          the Shell or Shell script being executed as passed in the  envi‐
          ronment  or  argument  list.   Subsequently, expands to the last
          argument to the previous command, after expansion.  Also set  to
          the  full  pathname  used  to  invoke  each command executed and
          placed in the environment exported to that command.  When check‐
          ing  mail,  this  parameter holds the name of the mail file cur‐
          rently being checked."$_" is the last argument of the previous command.

Используйте cd $_ для получения последнего аргумента предыдущей команды вместо cd !$ потому что cd !$ дает последний аргумент предыдущей команды в истории оболочки:

cd ~/
mkdir folder && cd !$

вы в конечном итоге домой (или ~ /)

cd ~/
mkdir newfolder && cd $_

вы попадаете в новую папку под домом !! (или ~/newfolder)

151
Jesús Carrera

Мне никогда бы не пришло в голову описать это поведение, потому что я вводил следующее почти ежечасно ...

$ mkdir someDirectory<ENTER>
$ cd !$

где Баш любезно заменяет !$ с последним словом последней строки; то есть длинное имя каталога, которое вы ввели.

Кроме того, завершение имени файла является вашим другом в таких ситуациях. Если ваш новый каталог был единственным файлом в папке, быстрый двойной TAB даст вам новый каталог без повторного входа в него.

Хотя это здорово, что bash позволяет вам выполнять такие распространенные задачи, как и другие ответы, я думаю, что лучше изучить функции редактирования командной строки, которые предлагает bash, чтобы при работе на другом компьютере не пропустить синтаксический сахар, который предоставляют ваши пользовательские скрипты.

30
Rob

Согласно Какие настройки вы сделали в своем профиле Shell для повышения производительности? , вот как я это делаю:

# make a directory and cd to it
mcd()
{
    test -d "$1" || mkdir "$1" && cd "$1"
}

это означает, что это также работает, если каталог уже существует.

17
Mikel

Если вы используете Oh My Zsh, есть команда take , которая делает именно это. Это будет выглядеть примерно так.

take myfolder

Я нашел это случайно. Я только что посмотрел, и он включен в этот читер из вики Oh My Zsh GitHub. Это довольно полезная команда, и, видимо, ее очень легко создать самостоятельно.

16
Jordan Harris

Или вы можете просто создать короткую переменную на лету и использовать ее дважды x = longproject ; mkdir $x ; cd $x - что, я признаю, все еще длиннее, чем использование функции шеллскрипта :)

3
sakisk

Я сделал скрипт, который создает каталог, а затем cd для него, затем я дал ему псевдоним. А вот Гист, где я это описываю.

https://Gist.github.com/rehnen/34236d6ff270ccaa74b6#mkdir-like-it-was-meant-to-be

0
Marcus Rehn

Вот небольшой вариант, который заслуживает упоминания:

function mkdir() {
    local dir=$1
    command mkdir "$dir"  &&  cd "$dir"
}

Добавьте это к вашему ~/.bash_profile и ​​затем вы можете использовать mkdir как обычно (как только вы source сделаете это), за исключением того, что теперь он будет выполнять вышеуказанную функцию вместо стандартной команды mkdir ,.

Обратите внимание, что это не проверяет ввод в соответствии с принятым ответ от Gilles , но демонстрирует, как вы можете (эффективно) переопределить встроенные функции.

из документов (слегка перефразируя):

command mkdir [args] выполняет mkdir с args, игнорируя любую функцию оболочки с именем mkdir. Выполняются только встроенные команды Shell или команды, найденные путем поиска в PATH. Если есть функция Shell с именем ls, выполняющая command ls внутри функции выполнит внешнюю команду ls вместо рекурсивного вызова функции

Я считаю, что builtin достигает результата, аналогичного command.

0
Arj

Добавление вспомогательной функции в BASH, ZSH или KSH

Создайте команду mkcd для вашей среды в одну строку

echo -e 'mkcd() {\n mkdir -p "$1" && cd $_\n}' >> ~/.${0//-/}rc && . ~/.${0//-/}rc
0
Proximo