A maneira mais simples é usar uma função de shell:
mkcd() {
mkdir -p -- "$1" && cd -- "$1"
}
Coloque-o no seu arquivo .bashrc para torná-lo disponível para você como outro comando de shell.
O motivo pelo qual ele não funciona como um script externo é cd altera o diretório atual do script em execução, mas não afeta o diretório atual. Isso é por design! Cada processo tem seu próprio diretório de trabalho que é herdado por seus filhos, mas o contrário não é possível.
A menos que seja parte de um pipeline, executado em segundo plano ou explicitamente em um subshell, uma função de shell não é executada em um processo separado, mas no mesmo, como se o comando tivesse sido originado. O shell de diretório atual pode ser alterado por uma função.
O && usado aqui para separar os dois comandos usados significa que, se o primeiro comando for bem-sucedido ( mkdir ), execute o segundo ( cd ). Conseqüentemente, se mkdir falhar ao criar o diretório solicitado, não faz sentido tentar entrar nele. Uma mensagem de erro é impressa por mkdir e é isso.
A opção -p usada com mkdir está lá para dizer a esse utilitário para criar qualquer diretório ausente que faça parte do caminho completo do nome do diretório passado como argumento. Um efeito colateral é que, se você pedir para criar um diretório já existente, a função mkcd não falhará e você terminará nesse diretório. Isso pode ser considerado um problema ou um recurso. No primeiro caso, a função pode ser modificada por exemplo, o que simplesmente avisa o usuário:
mkcd() {
if [ -d "$1" ]; then
printf "mkcd: warning, \"%s\" already exists\n" "$1"
else
mkdir -p "$1"
fi && cd "$1"
}
Sem a opção -p , o comportamento da função inicial teria sido muito diferente.
Se o diretório que contém o diretório a ser criado ainda não existir, mkdir falhará, assim como a função.
Se o diretório a ser criado já existir, mkdir também falhará e cd não será chamado.
Por fim, observe que a configuração / exportação de PWD é inútil, já que o shell já faz isso internamente.
Editar: eu adicionei a opção -- aos dois comandos para a função permitir um nome de diretório começando com um traço.