Como posso executar um comando no bash após qualquer alteração no $ PWD?

10

O zsh fornece algumas funções de gancho , incluindo chpwd para executar uma função. depois que o usuário altera os diretórios.

# zsh only
function greet() { echo 'hi'; }
chpwd_functions+=("greet")
cd .. # hi
pushd # hi
popd  # hi

Estou tentando emular isso no bash.

Restrições:

  • Deve funcionar em shells interativos e não interativos, o que eu acho que significa que não pode confiar em algo como $PROMPT_COMMAND
  • Não é possível redefinir cd , porque quero que ele funcione para qualquer comando que altere os diretórios (por exemplo, pushd e popd )
  • Ele precisa ser executado após o comando do usuário, então trap "my_function" DEBUG não funciona, a menos que eu possa dizer lá, "primeiro execute o $BASH_COMMAND we trapped, então faça isso. .. "Eu vejo que posso evitar a execução automática de $BASH_COMMAND se extdebug estiver ativado e a função trap retorna 1, mas não acho que quer forçar extdebug e retornar 1 para um comando bem-sucedido (mas modificado) parece errado.

A última parte - "executar após o comando do usuário" - é o que atualmente me deixou perplexo. Se eu puder executar uma função após cada comando, posso verificar se o diretório foi alterado desde a última verificação. Por exemplo:

function check_pwd() {
  # true in a new shell (empty var) or after cd
  if [ "$LAST_CHECKED_DIR" != "$PWD" ]; then
    my_function
  fi
  LAST_CHECKED_DIR=$PWD
}

Estou no caminho certo ou há uma maneira melhor? Como posso executar um comando no bash depois que o usuário altera os diretórios?

    
por Nathan Long 06.12.2014 / 04:25

3 respostas

2

Não há como atender a essas restrições

Parece que não há como resolver esse problema no bash com minhas restrições. Em geral, possíveis soluções são:

  • Substitua cd , pushd e popd , para que qualquer comando que altere os diretórios primeiro execute a função de gancho. Mas isso pode criar problemas porque 1) a substituição deve ter o cuidado de concluir a tabulação como o comando original e retornar o mesmo código de saída e 2) se mais de uma ferramenta usar essa abordagem, eles não poderão jogar bem juntos
  • Substituir todos os comandos que podem ser executados com as alterações do ambiente para executar primeiro a função de gancho. Isso é difícil porque há muitos desses comandos
  • trap 'my_function DEBUG so that every command will run the hook function. This is suboptimal because 1) it runs before every command, 2) it runs *before* cd ', não depois de 3) só pode haver uma função de depuração, então se outra ferramenta usar essa abordagem, eles não podem jogar bem juntos
  • Redefina $PROMPT_COMMAND para executar a função de gancho primeiro. Isso é insatisfatório porque não funciona em shells não interativos e porque, se outra ferramenta definir o comando prompt, eles não poderão jogar bem juntos.

Em suma, parece que a única grande solução seria se o bash fornecesse algo como chpwd_functions hook do zshell, mas parece impossível simular isso corretamente.

    
por 15.12.2014 / 15:27
1

Se o mantenedor não gostar de você mudar a definição para o cd, outra opção seria redefinir todos os comandos que usam esse ambiente no diretório:

for c in cmd1 cmd2 cmd3 cmd4 cmd5 ; do
    eval "$c() { check_pwd ; command $c \"\$@\" ; }"
done

Isso seria bastante eficiente porque o gancho do PWD e a configuração no diretório só seriam processados quando necessário.

Na sua função check_pwd de exemplo, posso alterar:

my_function

para:

my_function "$PWD"

para passar o novo cwd (pode ser mais modular, testável).

    
por 08.12.2014 / 18:57
0

Espero que isso ajude você:

Instale inotify-tools de acordo com sua distribuição.

inotifywait -emodify,create,delete -m /path/to/directory | while read line; do service httpd reload; done

No meu exemplo, o comando a seguir reiniciará httpd se alguma coisa mudar (Modificar, Criar, Excluir) no diretório especificado.

    
por 15.12.2014 / 11:37

Tags