Altera dir do script sem um “procedimento de shell” ou “sourcing the script”

3

Eu sei o que posso fazer com um procedimento de shell ou fonte o script em vez de executá-lo para cd o shell que estou usando. O que eu quero saber é que existe qualquer caminho para cd do "shell pai" (não tenho certeza se essa é a frase correta).

#!/bin/sh
# This is script.sh
cd $1
pwd

Aqui estão alguns resultados. ( Nota: esta não é a saída exata, apenas reduzi-a eliminando detalhes desnecessários. As linhas que são minhas entradas no shell começam com > .)

> mkdir foo
> ./script.sh foo
/home/myName/foo
> pwd
/home/myName

Este é o comportamento esperado, como eu entendo. Aqui está se eu "fonte" do script.

> . ./script.sh foo
/home/myName/foo
> pwd
/home/myName/foo

Sem fazer o sourcing do script e sem fazer disso um procedimento shell, existe alguma maneira de digitar ./script.sh foo result no shell que estou usando no diretório /home/myName/foo ?

    
por Captain Man 20.01.2016 / 18:08

4 respostas

2

Não, porque quando você invoca um script como ./script.sh foo , ele inicia uma subshell para executar o script para você. Quando essa sub-shell sai, você é colocado de volta no diretório em que estava quando iniciou o script. Você pode falsificar esse comportamento usando um script que faz algo assim:

#!/bin/bash
cd $1
bash

Isso colocará você em uma sub-shell depois de alterar os diretórios, que você terá que exit para voltar ao seu shell original.

Se você fizer a última linha:

exec bash

Você não terá que sair do novo shell, porque o novo shell substituirá o shell antigo. Fazer isso, no entanto, continua sendo um hack feio (IMHO).

    
por 20.01.2016 / 18:14
2

A resposta simples é não - isso é impossível.

Mas, se você estiver desesperado, poderá encontrar algumas soluções alternativas.

A abordagem mais fácil é quando existem apenas alguns diretórios que você conhece antecipadamente (no shell pai) em que o script pode tentar cd . Nesse caso, você pode definir uma armadilha para alguns sinais que seriam enviados a partir do script.

~ $ cat script
#!/bin/bash
kill -s SIGINT "$PPID"

~ $ trap 'cd /tmp' SIGINT
~ $ ./script
/tmp $

Uma maneira mais sofisticada de fazer isso é escrever o comando a partir do script na entrada padrão do shell pai. O procedimento (bastante complicado) é descrito aqui , mas o caso mais simples (com o diretório definido com antecedência) é novamente bastante fácil:

~ $ cat script
#!/bin/bash
printf '\e[5n' >/proc/"$PPID"/fd/0

~ $ bind '"\e[0n": "cd /tmp\n"'
~ $ ./script
/tmp $

Se você quiser passar um nome de diretório como um parâmetro do script para o shell pai, sugiro estudar as respostas do link acima.

    
por 20.01.2016 / 19:21
1

Você pode tentar:

gdb --batch -ex 'call chdir("/some/dir")' -p "$PPID"

Mas eu esperaria que a maioria dos shells se confundisse quando o diretório atual deles mudasse.

A propósito, na sintaxe do shell, você precisa de aspas em torno das variáveis e -- para separar as opções dos argumentos. Veja também o comportamento especial de cd quando não passou -P . Então seu código deve ser mais parecido com:

#! /bin/sh -
cd -P -- "$1"

Para ser equivalente a int main(int argc, char*argv[]){chdir(argv[1])} em C por exemplo (ainda seria ineficaz em alterar o diretório atual de outro processo)

    
por 26.01.2016 / 18:21
0

Um script é executado em um subshell, quaisquer mudanças de ambiente (diretório e variáveis) são locais para esse processo e são revertidas para as do processo de chamada quando o processo é encerrado (ou de outra forma o controle é devolvido).

Você pode executar comandos no shell atual (para que o efeito permaneça) por meio da fonte do script ( . here/is/the/script ) ou definindo uma função do shell. As funções do shell podem ser bastante complexas e, crucialmente, são executadas no processo de shell atual. Nem todas as shells suportam funções (bash faz).

    
por 26.01.2016 / 22:19