Script para alterar o diretório atual (cd, pwd)

44

Eu quero executar um script para simplesmente alterar o diretório de trabalho atual:

#!/bin/bash
cd web/www/project

Mas, depois de executá-lo, o atual pwd permanece inalterado! Como eu posso fazer isso?

Sony Santos
fonte

Respostas:

63

É um comportamento esperado, e já discutido várias vezes.

O script é executado em uma subshell e não pode alterar o diretório de trabalho do shell pai. Seus efeitos são perdidos quando termina.

Para alterar o diretório permanentemente, você deve originar o script, como em

. ./script
enzotib
fonte
8
@ Sony: Observe que você deve usar returnpara escapar de um script originado dessa maneira, não exit- eles são como funções do shell e exitsairão do shell que originou o script.
Charles Stewart
@CharlesStewart De fato, não estou familiarizado com scripts de origem. Obrigado!
Sony Santos
5
é source ./scripto mesmo?
Amyassin
2
@amyassin: sim, é
enzotib
2
1. .e sourcesão iguais no bash. 2. não precisamos usar o ./nome do arquivo antes, se estiver no mesmo diretório. Não há problema em executar apenas isso:. script
sobi3ch 16/06
19

Para pequenas tarefas como essa, em vez de criar script, crie um alias como este,

$ alias cdproj='cd /dir/web/www/proj'

Você deve adicionar isso ao seu .bashrcarquivo, se desejar, para cada shell interativo.

Agora você pode executar isso como $ cdproj.

Sachin Divekar
fonte
1
Você também pode fazer com que o script faça eco dos comandos a serem executados e, em seguida, use eval `./script` ou eval $(./script)para executar esses comandos. Essa é uma abordagem comum para comandos que precisam atualizar o ambiente do shell de chamada.
Keith Thompson
2
Apenas tenha muito cuidado com o que você produz, se quiser seguir a evalabordagem.
Jw013
13

Use exec bashno final

Um script bash opera em seu ambiente atual ou em seus filhos, mas nunca em seu ambiente pai.

No entanto, essa pergunta geralmente é feita porque alguém deseja ser deixado no prompt do bash em um determinado diretório após a execução de um script bash de outro diretório.

Se for esse o caso, simplesmente execute uma instância do bash filho no final do script:

#!/usr/bin/env bash
cd desired/directory
exec bash

Isso cria um novo subshell. Digite exitpara retornar ao primeiro shell em que o script foi iniciado inicialmente.

Serge Stroobandt
fonte
É melhor apenas fonte do script, como na resposta aceita: o uso execé normalmente considerado o último recurso de um canalha .. :) #
31596
1
esse truque não funciona no debian 9 stretch.
Vdegenne
3
Este é o caminho errado para fazer isso!
Dennis Williamson
4
Como ninguém detalhou os problemas com isso (estou olhando para você, @Dennis): (1) Cada vez que você executa isso, ele cria um novo e persistente processo de bash. Faça isso dez ou vinte vezes em uma sessão e você terá de 11 a 21 processos acumulados. Isso pode afetar o desempenho e, se você tentar encerrar a sessão de maneira limpa, digitando exit(ou Ctrl + D), precisará fazer isso 11 a 21 vezes. (2) Outra desvantagem do uso de um script executável é que, se você definir quaisquer opções de shell (por exemplo,  dotglobou  globstar) em sua sessão interativa de shell, você as perderá, porque está iniciando um novo shell.
G-Man Diz 'Reinstate Monica' em
1
Solução muito boa! Eu reescrevi meu alias em bash_profile, agora ele é um script armazenado em um arquivo separado. Eu uso o script para ir para uma pasta temporária recém-criada. E agora é ainda mais fácil ter uma sessão temporária do bash. SRP em ação! Obrigado!
artyom.razinov 18/10
8

Embora existam respostas que executam a ação exata que você deseja, um método mais padrão para esse fim é criar um link simbólico:

ln -s ~/web/www/project proj   #use full path to dir!

Em seguida, você pode cdacessar o diretório usando o nome proj:

cd proj

Este método é mais flexível porque você pode acessar arquivos usando o nome abreviado sem cd:

ls proj/   #note the endslash!
vim proj/file.x
corvinus
fonte
4

Se você mudar entre diretórios distantes no sistema de arquivos. Vou recomendar o salto automático .

stnly
fonte
4

Depende do que você fará, outra solução pode ser criar uma função em vez de um script.

Exemplo:

Crie uma função em um arquivo, digamos /home/aidin/my-cd-script:

function my-cd() {
  cd /to/my/path
}

Em seguida, inclua-o no seu arquivo bashrcou zshrc:

# Somewhere in rc file
source /home/aidin/my-cd-script

Agora você pode usá-lo como um comando:

$ my-cd
Auxílio em
fonte
0

Por que não usar "exec" é costurado para fazer exatamente o que eu desejo.

#!/bin/bash

cd someplace
exec bash

~/someplace
Paulo
fonte
1
Cuidado com as coisas que parecem ser o que você deseja. (Um cavalo gigante de madeira! Exatamente o que eu queria!) Cada vez que você executa isso, ele cria um novo e persistente processo de bash. Faça isso dez ou vinte vezes em uma sessão e você terá 11 a 21 processos bash empilhados. Isso pode afetar o desempenho e, se você tentar finalizar a sessão corretamente, digitando exit(ou Ctrl + D), será necessário fazer isso 11 a 21 vezes.
G-Man diz 'Reinstate Monica' em
Eu definitivamente podia ver onde isso seria um problema. Para mim, embora eu esteja usando uma vez, fazendo o trabalho de que preciso e saindo, se essa for a única desvantagem que posso viver com isso. Por outro lado, se houver uma solução melhor, estou disposto a olhar para ela.
paul
A resposta de Aidin a essa pergunta , usando uma função shell, e a resposta de Sachin Divekar , usando um alias, são (IMO) soluções melhores do que usar um script. PS Outra desvantagem do uso de um script é que, se você definir qualquer opção de shell (por exemplo,  dotglobou  globstar), você as perderá, porque está iniciando um novo shell. … (Continua)
G-Man diz 'Reinstate Monica'
(Continua) ... PPS Acabei de notar que você está, basicamente, reiterando a resposta de Serge Stroobandt e dizendo '' Por que não fazer isso? '' No  Stack Exchange , esperamos respostas para fornecer novas idéias e / ou informações, e não apenas discutir outras respostas.
G-Man Diz 'Reinstate Monica' em
-1

Você pode fazer isso usando uma função ou usando && Os exemplos abaixo instalam o Zabbix e criam um arquivo com uma linha dentro dele.

Ex:

#!/bin/bash

# Create Function:
installZabbix(){
    cd /usr/src/zabbix-4.2.4;
    ./configure --enable-agent;
    make install;
    cd /usr/src/;
    >file;
    echo "Hi, this is a file." >>file;
}

# Call the function:
installZabbix

ou:

#!/bin/bash
cd /usr/src/zabbix-4.2.4 && ./configure --enable-agent && make install && cd /usr/src && >file && echo "Hi, this is a file." >>file
Raul Chiarella
fonte