Não há comando interno, mas você pode escrever facilmente uma função que chama mkdir
then cd
:
mkcd () {
mkdir "$1"
cd "$1"
}
Coloque este código no seu arquivo ~/.bashrc
(ou ~/.kshrc
para usuários do ksh ou ~/.zshrc
para usuários do zsh). Define uma função chamada mkcd
. "$1"
será substituído pelo argumento da função quando você executá-lo.
Esta versão simples tem vários defeitos:
- Você não pode criar uma cadeia de subdiretórios de uma só vez. Correção: passe a opção
-p
paramkdir
. (Isso pode ou não ser desejável, pois aumenta o risco de um erro de digitação não ser detectado, por exemplo,mkcd mydierctory/newsub
terá prazer em criarmydierctory
emydierctory/newsub
quando você pretende criarnewsub
dentro domydirectory
existente.) - Se o argumento começar com
-
, mas não for apenas-
, entãomkdir
ecd
o interpretarão como uma opção. Se for apenas-
, entãocd
interpretará como$OLDPWD
. Se for+
seguido por 0 ou mais dígitos, entãocd
em zsh irá interpretá-lo como um índice na pilha de diretórios. Você pode corrigir o primeiro problema, mas não os outros dois, passando--
antes do argumento. Você pode corrigir todos esses problemas, adicionando./
ao argumento se for um caminho relativo. -
mkdir
não segueCDPATH
, mascd
, portanto, se você definiuCDPATH
como um valor que não começa com.
(uma configuração reconhecidamente um tanto incomum), entãocd
pode levar você a um diretório diferente daquele que acabou de ser criado. Colocar./
nos caminhos relativos corrige isso (faz com queCDPATH
seja ignorado). - Se
mkdir
falhar, ele tentará executarcd
. Correção: use&&
para separar os dois comandos.
Ainda bastante simples:
mkcd () {
case "$1" in /*) :;; *) set -- "./$1";; esac
mkdir -p "$1" && cd "$1"
}
Esta versão ainda tem o potencial de tornar cd
em um diretório diferente daquele que mkdir
acabou de criar em um caso de borda: se o argumento para mkcd
contiver ..
e passar por um link simbólico . Por exemplo, se o diretório atual for /tmp/here
e mylink
for um link simbólico para /somewhere/else
, então mkdir mylink/../foo
criará /somewhere/else/foo
, enquanto cd mylink/../foo
será alterado para foo
. Não é suficiente procurar links simbólicos no argumento, porque o shell também rastreia links simbólicos em seu próprio diretório atual, portanto, cd /tmp/mylink; mkdir ../foo; cd ../foo
não é alterado para o novo diretório ( /somewhere/else/foo
), mas para /tmp/foo
. Uma correção para isso é deixar o cd
builtin resolver todos os componentes ..
path primeiro (não faz sentido usar foo/..
if foo
não existe, portanto mkdir
nunca precisa ver nenhum ..
).
Chegamos a essa versão robusta, embora um pouco sangrenta:
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
}
(Exercício: por que estou usando um subshell para a primeira chamada cd
?)
If mkdir fails, I want to be sure not to change the current directory. Changing back with cd - or $OLDPWD isn't good enough if the shell doesn't have permission to change into its current directory. Also, calling cd updates OLDPWD, so we only want to do it once (or restore OLDPWD).
Há também formas menos especializadas de não precisar redigitar a palavra da linha anterior:
- Digite
cd
, então Esc . (ou Alt + . ) para inserir o último argumento do comando anterior. -
cd !$
executacd
no último argumento do comando anterior. - Pressione Para cima para recuperar a linha de comando anterior e edite-a para alterar
mkdir
paracd
.