Como eu faço um comando cd ter efeito fora do subshell do script bash? [duplicado]

0

Eu fiz este script:

#!/bin/bash

if [[ $# -ne 1 ]]; then
  echo "only use one argument"
  exit 1
fi

mkdir $1
sleep 0.5
cd $1

exit 0

Eu queria fazer um script que eu colocaria posteriormente em / usr / bin, de modo que sempre que eu escrevesse crdir asd ele criaria o diretório e automaticamente mudaria meu diretório atual para o novo diretório.

Desta forma, não funciona, porque o script schell aparentemente é um subshell, e o comando cd não terá efeito fora do subshell, então como eu faria isso?

Eu li on-line que eu deveria "fonte", corri com um ponto na frente, como . ./crdir asd , mas antes de tudo, quando eu tentei isso, ssh foi desconectado da máquina, e em segundo lugar, isso wouldn ' funciona do jeito que eu queria que funcionasse, como um comando.

Alguma dica?

EDIT: Eu também tentei mkdir aaa; cd !# mas não funcionou, levou !# como o argumento do comando anterior.

    
por iamAguest 28.08.2018 / 16:12

2 respostas

4

Crie uma função:

crdir() {
  if [ "$#" -eq 1 ]; then
    mkdir -p -- "$1" && cd -P -- "$1"
  else
    echo >&2 "Usage: crdir <directory-path>"
    return 1
  fi
}

Que você pode colocar em seu ~/.bashrc .

Sua abordagem . crdir também funcionaria (em bash e outros shells cujo . pode receber argumentos), mas você precisará remover esse exit 0 que faz com que o shell seja encerrado. Observe também que, quando não estiver no modo POSIX, bash procurará o arquivo para a origem no diretório atual, se ele não puder ser encontrado em $PATH , o que o torna um pouco perigoso (no mesmo nível que a adição de . ou uma entrada vazia no final de $PATH ).

Além disso, se . crdir for chamado sem argumentos, o script herdará o parâmetro posicional do shell. Por exemplo, set foo; . crdir não retornaria um erro e criaria o diretório foo .

Algumas outras notas no seu script:

#!/bin/bash

Observe que a explosão é ignorada (é apenas vista como um comentário) quando o arquivo é originado.

if [[ $# -ne 1 ]]; then
  echo "only use one argument"

É preferível enviar mensagens de erro no stderr ( echo >&2 text ).

  exit 1
fi

mkdir $1

Deixar expansões de parâmetros sem aspas tem um significado especial em bash , você quase nunca deve fazer isso.

Além disso, se $1 começar com - , ele será tratado como uma opção por mkdir . Você precisaria usar o marcador -- fim-de-opção para informar mkdir o conteúdo de $1 não é uma opção, mesmo que comece com - .

Você também não está verificando se o comando mkdir foi bem-sucedido.

Você também pode querer usar a opção -p que informa mkdir para criar todos os componentes de diretório e também faz com que mkdir não retorne falha se o diretório já existir. Então:

 mkdir -p -- "$1" &&
sleep 0.5

Não precisa dormir. Você pode ter certeza de que o diretório foi criado quando mkdir retornar com êxito.

cd $1

Novamente, você tem os problemas de cotação e - . Além disso, em bash você precisa da opção -P para cd para interpretar caminhos da mesma maneira que outros utilitários como mkdir . Então:

 cd -P -- "$1"

(ignorando por enquanto um caminho chamado - ou $CDPATH , que eu espero que você não use ou use apenas com valores sônicos).

exit 0

Novamente, você não está verificando o status de saída de cd e retornando com um status de saída sucesso , mesmo se mkdir ou cd falhar. Quando um script é originado, ele é interpretado pelo shell de origem, para que exit faça com que ele saia.

Aqui, eu reescreveria o script como:

if [ "$#" -eq 1 ]; then
  mkdir -p -- "$1" && cd -P -- "$1"
else
  ! echo >&2 "Usage: crdir  <directory-path>"
fi
    
por 28.08.2018 / 16:21
0

Que tal uma função:

crdir() { mkdir $1; cd $1; }
    
por 28.08.2018 / 16:24