Alterar o diretório atual de um script Bash


190

É possível alterar o diretório atual de um script?

Quero criar um utilitário para navegação de diretório no Bash. Eu criei um script de teste que se parece com o seguinte:

#!/bin/bash
cd /home/artemb

Quando executo o script no shell Bash, o diretório atual não muda. É possível alterar o diretório shell atual de um script?


2
Apenas uma sugestão de aprimoramento: se você usar pushd(possivelmente redirecionado para >/dev/nullsuprimir sua saída) em vez de cd, poderá retornar posteriormente ao diretório anterior com popd.
mklement0

Respostas:


173

Você precisa converter seu script em uma função shell:

#!/bin/bash
#
# this script should not be run directly,
# instead you need to source it from your .bashrc,
# by adding this line:
#   . ~/bin/myprog.sh
#

function myprog() {
  A=$1
  B=$2
  echo "aaa ${A} bbb ${B} ccc"
  cd /proc
}

O motivo é que cada processo tem seu próprio diretório atual e, quando você executa um programa a partir do shell, ele é executado em um novo processo. O "cd", "pushd" e "popd" padrão são incorporados ao interpretador de shell para que afetem o processo do shell.

Ao tornar seu programa uma função de shell, você está adicionando seu próprio comando em processo e qualquer alteração de diretório é refletida no processo de shell.


2
como você faria isso no tcsh?
joedborg

4
+1. Uma coisa que notei estava no arquivo: precisamos definir a função antes de chamá-la. Pode ajudar alguém tão inexperiente quanto eu.
Bhushan

Qual é a grande diferença entre definir uma função e criar um alias?
hellogoodbye

1
Depois de criar esse arquivo myprog.sh e adicioná-lo ao .bashrc, como executo o script? Devo chamar minha função de outro arquivo shell ou diretamente do shell? Parece que não funciona de nenhuma maneira ... #
Andrea Silvestri

1
@AndreaSilvestri Efetue logout e logon novamente ou na origem .bashrc. Adicioná-lo ao .bashrc não faz nada até que o .bashrc seja executado.
precisa

213

Quando você inicia seu script, é criado um novo processo que herda apenas seu ambiente. Quando termina, termina. Seu ambiente atual permanece como está.

Em vez disso, você pode iniciar seu script assim:

. myscript.sh

Ele .avaliará o script no ambiente atual, para que possa ser alterado


4
+1 porque você está certo. Embora eu sinceramente duvide que ele queira criar um script de mudança de diretório sempre que precisar. Além disso, as .shextensões são totalmente eww. Não os use.
Lhunath 17/05/09

1
Sim, geralmente é melhor não usá-lo dessa maneira. Na maioria das vezes, você fica feliz por seu ambiente atual não sofrer. Mas então eu tenho scripts para fazer algumas tarefas de configuração para mim, incluindo mudar para o lugar certo e então eu. eles também. Btw. .sh é obviamente uma questão de estilo pessoal. Eu provavelmente não o usaria durante a instalação de scripts em todo o sistema. Mas no meu ~ / bin eu usá-los para saber o que é o que :)
Norbert Hartl

11
@lhunath Por que as extensões .sh são totalmente eww?
Carl Pritchett


1
Para mim, o raciocínio desse artigo é falso. Parece que o resultado foi conhecido antecipadamente, mas encontrar razões para isso não foi tão fácil. Por isso, sustento meu argumento: é uma questão de estilo pessoal, nada mais.
Norbert Hartl

55

À luz da ilegibilidade e da complicação excessiva das respostas, acredito que é isso que o solicitante deve fazer

  1. adicione esse script ao PATH
  2. execute o script como . scriptname

O .(ponto) garantirá que o script não seja executado em um shell filho.


38

Juntando o exposto, você pode criar um alias

alias your_cmd=". your_cmd"

se você não quiser escrever o "" inicial. toda vez que você desejar originar seu script no ambiente shell, ou se você simplesmente não quiser se lembrar, isso deve ser feito para que o script funcione corretamente.


Isso permanecerá persistente nas reinicializações?
SDsolar 17/05/19

1
@SDsolar Você precisa adicionar isso ao seu arquivo ~ / .bashrc para torná-lo persistente. Funciona como um encanto para mim.
Rafał G.

Pode ser colocado em ~ / .bash_aliases
Champ

O @Champ ~/.bash_aliasesnem sempre é fornecido quando o Bash é iniciado.
Mateusz Piotrowski

31

Se você estiver usando o bash, tente o alias:

no arquivo .bashrc, adicione esta linha:

alias p='cd /home/serdar/my_new_folder/path/'

quando você escreve "p" na linha de comando, ele altera o diretório.


1
+1 para o alias. A função shell é interessante, mas o OP pediu uma navegação simples com o cd. Eu estou supondo que a maioria das pessoas precisa de um script como este para ramos de código fonte de navegação e para que alias é suficiente
Brad Dre

19

Se você executar um script bash, ele funcionará no ambiente atual ou nos de seus filhos, nunca no pai.

Se o objetivo é executar seu comando: goto.sh / home / test Então, trabalhe interativamente em / home / test. Uma maneira é executar um subshell interativo bash dentro do seu script:

#!/bin/bash
cd $1
exec bash

Dessa forma, você estará em / home / test até sair (exit ou Ctrl + C) desse shell.


Eu pensei que isso resolveria o problema de um script de shell que eu estava executando, mas, em vez disso, inicia o shell e esquece o que eu queria.
vwvan

13

Com pushd, o diretório atual é empurrado na pilha de diretórios e é alterado para o diretório especificado, popd coloca o diretório no topo da pilha e muda para ele.

pushd ../new/dir > /dev/null
# do something in ../new/dir
popd > /dev/null

2
Isso responde à minha pergunta - implantar ativamente esta solução em um script init do S3 e funciona perfeitamente bem. Obrigado @seb.
19h

5

Simplesmente vá para

yourusername/.bashrc (or yourusername/.bash_profile on MAC) by an editor

e adicione este código ao lado da última linha:

alias yourcommand="cd /the_path_you_wish"

Então saia do editor.

Então digite:

source ~/.bashrc or source ~/.bash_profile on MAC.

agora você pode usar: seu comando no terminal



3

Basicamente usamos cd.. para voltar de todos os diretórios. Eu pensei em facilitar, fornecendo o número de diretórios com os quais você precisa voltar de cada vez. Você pode implementar isso usando um arquivo de script separado usando o comando alias. Por exemplo:

code.sh

#!/bin/sh
 _backfunc(){
 if [ "$1" -eq 1 ]; then
  cd ..
 elif [ "$1" -eq 2 ]; then
  cd ../..
 elif [ "$1" -eq 3 ]; then
  cd ../../..
 elif [ "$1" -eq 4 ]; then
  cd ../../../..
 elif ["$1" -eq 10]; then
  cd /home/arun/Documents/work
 fi
 }
alias back='_backfunc'   

Depois de usar source code.sho shell atual, você pode usar:

$back 2 

para voltar duas etapas do diretório atual. Explicado em detalhes por aqui . Também é explicado por lá como colocar o código em ~ / .bashrc, para que cada novo shell aberto tenha automaticamente esse novo comando de alias. Você pode adicionar um novo comando para acessar diretórios específicos, modificando o código adicionando mais if conditionse diferentes argumentos. Você também pode extrair o código do git aqui .


Boa solução, então você nunca atrapalhar o seu perfil festa :)
J4cK

0

Essa abordagem é mais fácil para mim.

Suponha que em um iMac pessoal em que você seja um administrador, no diretório padrão quando uma janela de comando for aberta, / Users / jdoe, esse seja o diretório para: /Users/jdoe/Desktop/Mongo/db.3.2.1 / bin.

Estas são as etapas que podem fazer o trabalho:

  1. vi mongobin, no qual entrei: cd /Users/jdoe/Desktop/Mongo/db.3.2.1/bincomo a primeira linha.
  2. chmod 755 mongobin
  3. source mongobin
  4. pwd

Voila!


0

Eu também criei um utilitário chamado bode que você pode usar para facilitar a navegação.

Você pode ver o código fonte no GitHub .

A partir da v2.3.1, a visão geral do uso é semelhante a esta:

# Create a link (h4xdir) to a directory:
goat h4xdir ~/Documents/dev

# Follow a link to change a directory:
cd h4xdir

# Follow a link (and don't stop there!):
cd h4xdir/awesome-project

# Go up the filesystem tree with '...' (same as `cd ../../`):
cd ...

# List all your links:
goat list

# Delete a link (or more):
goat delete h4xdir lojban

# Delete all the links which point to directories with the given prefix:
goat deleteprefix $HOME/Documents

# Delete all saved links:
goat nuke

# Delete broken links:
goat fix

0

Eu gosto de fazer a mesma coisa em projetos diferentes sem disparar um novo shell.

No seu caso:

cd /home/artemb

Salve the_script como:

echo cd /home/artemb

Em seguida, acenda-o com:

\`./the_script\`

Então você chega ao diretório usando o mesmo shell.



0

Declare seu caminho:

PATH='/home/artemb'     
cd ${PATH}

0

Basta escrever PWDe exportá-lo para o seu script, e a alteração persistirá.

export PWD=/your/desired/directory
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.