Por que "cd" não funciona em um shell script?

43

Eu só quero escrever um script que mude meu diretório .

Coloquei os comandos abaixo no arquivo /home/alex/pathABC

#!/bin/sh
cd /home/alex/Documents/A/B/C
echo HelloWorld

Eu fiz chmod +x pathABC.

No terminal, enquanto estiver dentro /home/alex, corro ./pathABC, mas a saída é justa HelloWorlde o diretório atual não é alterado.

Então o que está errado?

Mohammad Reza Rezwani
fonte

Respostas:

74

Como outros explicaram, o diretório é alterado no processo filho do seu script, não no processo terminal do qual o script é chamado. Depois que o processo filho morre, você volta ao terminal que fica onde estava.

Várias alternativas:

1. Link simbólico

Coloque um link simbólico em sua casa no caminho longo que você deseja acessar facilmente

$ ln -s /home/alex/Documents/A/B/C ~/pathABC

em seguida, acesse o diretório com:

$ cd ~/pathABC

2. Alias

Coloque um alias no seu ~ / .bashrc:

alias pathABC="cd /home/alex/Documents/A/B/C"

( daqui )

3. Função

Crie uma função que altera o diretório, a função é executada no processo do seu terminal e pode alterar seu diretório.

( daqui )

4. Evite correr quando criança

Crie seu script em vez de executá-lo. O fornecimento (feito por .ou source) faz com que o script seja executado no mesmo shell em vez de ser executado em seu próprio subshell.

$ . ./pathABC

( daqui e aqui )

5. vars compatíveis com CD

Defina a cdable_varsopção no seu ~/.bashrce crie uma variável de ambiente para o diretório:

shopt -s cdable_vars
export pathABC="/home/alex/Documents/A/B/C"

Então você pode usar cd pathABC

( daqui )

Gauthier
fonte
15
Agora eu entendo o uso de source! Eu sempre me perguntei por que eu faço source .bashrce nãobash .bashrc
hytromo
A opção 3 funcionou muito bem. Acabei de definir uma função go_to_wherever () {cd my / directory} no início do meu script. Chamado antes de executar as operações nesse diretório.
I2097i
> 5. Vars compatíveis com CD - não é cd $pathABC?
Loxaxs
7

Quando você executa o script em um terminal, um processo filho é executado. Neste programa filho, ou seja, seu script será alterado para qualquer diretório especificado. Mas no processo pai, ou seja, onde você executa o script ainda está no caminho antigo. Ou simplesmente podemos dizer:

The scope of cd command is only for child process not parent

Tingrammer
fonte
2
Além disso, o @alex para obter o efeito que você procura, execute o script no processo pai, fornecendo-o: ou . pathABCou source pathABC.
zwets
4

Você está cometendo um erro de raciocínio. Enquanto o shell atual permanece no mesmo diretório, o script foi movido para o novo diretório.

Você pode ver isso criando outro script no novo diretório e executando-o a partir do seu script, depois que ele mudou de diretório:

#!/bin/sh
cd /home/alex/Documents/A/B/C && ./another_script.sh # (if it is executable)

O segundo script seria executado a partir do novo diretório.

HelloWorld 

é apenas a saída do script.

Jacob Vlijm
fonte
3
HelloWorld não é "voltou" para o shell pai, de saída para a saída padrão
Mog
Pode ser mais claro se você acabou de executar pwdno novo diretório, em vez de adicionar um script totalmente novo à situação.
Wjandrea
0

Como o hello world é apenas uma declaração de rastreamento, vamos tentar o seguinte:

Crie um arquivo de script bash cd.shcontendo:

#!/bin/bash
echo "/home/mike/Documents/A/B/C"
  • A .shextensão é uma convenção antiga de atribuir uma extensão aos nomes de arquivos do script bash. É puramente cosmético e geralmente desnecessário. No entanto, neste caso, é importante diferenciar do cdcomando principal .

Marque o arquivo de script bash como executável usando:

chmod a+x cd.sh

Agora execute o arquivo:

$ cd $(./cd.sh)
bash: cd: /home/alex/Documents/A/B/C: No such file or directory
  • cd todos nós sabemos.
  • $(...) executa o comando entre parênteses e retorna a saída.
  • Se cd.shestava no seu caminho, você não precisa especificar onde está. Nós prefixamos com ./para especificar o comando no diretório atual.
  • A echosaída do cd.shscript é enviada de volta ao pai via $(...). O pai (nosso prompt de shell) usa essa saída e a passa para o cdcomando Linux .

Como outros já mencionaram, um processo filho não pode alterar o diretório dos pais. Essa é uma maneira pela qual a criança pode dizer aos pais para onde ir após o término do processo.

WinEunuuchs2Unix
fonte
@wjandrea Isso é o que você ganha por codificar em um telefone! Acabei de chegar em casa, eu vou consertar. Obrigado. Hum apenas verificado e funciona bem. Talvez seja a sua 14.04versão que li cerca de uma hora atrás?
WinEunuuchs2Unix
Bem, você mudou totalmente o script. Anteriormente, era apenas um comando:, cd /home/mike/Documents/A/B/Cque não produzia nenhuma saída. Agora é echo "/home/mike/Documents/A/B/C", o que produz saída.
Wjandrea
@wjandrea É verdade que também mudei totalmente a maneira de chamar o script. Em vez de simples ./cd.sh, agora é, cd $(./cd.sh)mas cumpre o objetivo da criança alterar o diretório atual dos pais. Sim, não é convencional, mas é outra maneira de fazer isso que espero que as pessoas achem interessantes.
WinEunuuchs2Unix