Как я могу запустить команду в bash после любого изменения в $ PWD?

zsh предоставляет некоторые хорошие функции hook , включая chpwd для запуска функции после того, как пользователь меняет каталоги.

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

Я пытаюсь подражать этому в bash.

Ограничения:

  • Он должен работать как в интерактивных, так и в неинтерактивных оболочках, что, я думаю, означает, что он не может полагаться на что-то вроде $PROMPT_COMMAND
  • Он не может переопределить cd , потому что я хочу, чтобы он работал для любой команды, которая меняет каталоги (например, pushd и popd )
  • Он должен запускаться после команды пользователя, поэтому trap "my_function" DEBUG не работает, если я не могу как-то сказать там, «сначала запустите $BASH_COMMAND мы оказались в ловушке, а затем сделаем это …» Я вижу, что я могу избежать автоматический запуск $BASH_COMMAND если включен extdebug и функция trap возвращает 1, но я не думаю, что хочу заставить extdebug , и возврат 1 для успешной (но модифицированной) команды кажется неправильным.

Последняя часть – «запускается после команды пользователя» – это то, что в настоящее время меня озадачивает. Если я могу запустить функцию после каждой команды, я могу проверить, изменился ли каталог с момента последнего обновления. Например:

 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 } 

Я на правильном пути, или есть лучший способ? Как я могу запустить команду в bash после того, как пользователь меняет каталоги?

Если разработчику не нравится, что вы меняете определение для cd, другим вариантом будет переопределение всех команд, которые используют эту среду в каталоге:

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

Это было бы очень эффективно, потому что перехват PWD и конфигурация в директории обрабатывались только по мере необходимости.

В вашем примере функции check_pwd я могу изменить:

 my_function 

чтобы:

 my_function "$PWD" 

чтобы перейти в новую cwd (может быть более модульной, проверяемой).

Ничто не сравнится с этими ограничениями

Похоже, что нет возможности решить эту проблему в bash с моими ограничениями. В общем, возможные решения:

  • Переопределите cd , pushd и popd , чтобы любая команда, которая меняет каталоги, сначала запускает функцию hook. Но это может создать проблемы, потому что 1) переопределение должно быть тщательным, чтобы вкладка была завершена, как исходная команда, и возвращала один и тот же код выхода и 2) если более одного инструмента использует этот подход, они не могут хорошо играть вместе
  • Переопределите все команды, которые могут быть запущены с изменениями среды, чтобы сначала запустить функцию hook. Это сложно, потому что таких команд много
  • 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* so that every command will run the hook function. This is suboptimal because 1) it runs before every command, 2) it runs *before* cd`, а не после 3) может быть только одна функция отладки, поэтому, если другой инструмент использует этот подход, они не могут хорошо играть вместе
  • Переопределите $PROMPT_COMMAND чтобы $PROMPT_COMMAND запустить функцию hook. Это субоптимально, потому что он не будет работать в неинтерактивных оболочках, а потому, что если другой инструмент определяет команду приглашения, они не могут хорошо взаимодействовать.

Короче говоря, похоже, единственное замечательное решение было бы, если бы bash предоставил что-то вроде chpwd_functions chpwd_functions , но кажется, что это невозможно правильно имитировать.

Я надеюсь, это поможет вам:

Установите инструменты inotify в соответствии с вашим дистрибутивом.

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

В моем примере следующая команда перезапустит httpd если что-то изменится (Modify, Create, Delete) в указанном каталоге.