$ PWD'deki herhangi bir değişiklikten sonra bash komutunu nasıl çalıştırabilirim?


10

zsh , kullanıcı dizinleri değiştirdikten sonra bir işlevi çalıştırmak da dahil olmak üzere bazı güzel kanca işlevleri sağlar chpwd.

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

Bunu bash'da taklit etmeye çalışıyorum.

Kısıtlamalar:

  • Hem interaktif hem de interaktif olmayan mermilerde çalışmalı, bence bu gibi bir şeye güvenemez $PROMPT_COMMAND
  • Yeniden tanımlayamaz cd, çünkü dizinleri değiştiren herhangi bir komut için çalışmasını istiyorum (ör. pushdVe popd)
  • Bu çalıştırmalısınız sonra böylece, kullanıcının komutuyla trap "my_function" DEBUG, ben bir şekilde orada söyleyebiliriz sürece, değil nasıl çalışır "ilk çalıştırmak $BASH_COMMANDsonra da bunu, tuzağa biz ..." Ben otomatik çalışmasını önleyebilirsiniz görüyoruz arasında $BASH_COMMAND ise extdebug etkindir ve tuzak işlevi 1 döndürür, ancak zorlamak istediğimi sanmıyorum extdebugve 1başarılı (ama değiştirilmiş) bir komut için geri dönmek yanlış görünüyor.

Son bölüm - "kullanıcının komutundan sonra koş" - şu anda beni güdük. Ben ise edebilir her komutun ardından bir işlev çalıştırın, bunun son kontrol beri dizin değişip değişmediğini kontrol olabilir. Örneğin:

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
}

Doğru yolda mıyım yoksa daha iyi bir yol var mı? Kullanıcı dizinleri değiştirdikten sonra bash komutunu nasıl çalıştırabilirim?


3
Neden yeniden tanımlamak değil cd, pushdve popd? Dizini değiştirmek için başka kaç yol var?
jw013

@ jw013, bu kodun, sürdürücünün cdprensip olarak yeniden tanımlanmadığını özellikle listelediği açık kaynaklı bir projeye girmesi amaçlanmıştır .
Nathan Long

Ayrıca - "dizini değiştirmek için başka yollar var" - Bilmiyorum, bu açıkça onları listelemeye güvenmemeyi tercih ederim başka bir nedenidir.
Nathan Long

Bunu neden yapmak istiyorsun? İşleviniz birçok programı (C, Java, ..) frenleyebilir. Kullandığım komut dosyalarında MYBIN=$( cd -P -- "$(dirname -- "$(command -v -- "$0")")" && pwd -P )Lütfen güvenilir Unix komutlarını değiştirmeyin.
Walter A

1
@NathanLong bu sadece işletim sistemim için . İşletim sistemi burada önemsiz görünüyor. İşletim sistemi önemli mi? Sorunuzda önemli olan kabuk ve bashüzerinde çalıştığı tüm işletim sistemlerinde hemen hemen aynı şekilde çalışan, özellikle soruyor gibi görünüyorsunuz .
jw013

Yanıtlar:


2

Bu kısıtlamalara uymanın bir yolu yok

Bu sorunu kısıtlarımla bash'da çözmenin bir yolu yok gibi görünüyor. Genel olarak, olası çözümler şunlardır:

  • Geçersiz Kıl cd, pushdve popdbu yüzden dizinleri değiştiren komut ilk kanca işlevini çalışacağı. Ancak bu sorun yaratabilir, çünkü 1) geçersiz kılma, orijinal komut gibi tam sekmeye ve aynı çıkış kodunu döndürmeye dikkat etmelidir ve 2) birden fazla araç bu yaklaşımı kullanıyorsa, birlikte iyi oynayamazlar
  • İlk olarak kanca işlevini çalıştırmak için ortam değişiklikleriyle çalıştırılabilen tüm komutları geçersiz kılın. Bu zor çünkü böyle birçok komut var
  • trap 'my_functionDEBUG 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'ten sonra değil) sadece bir hata ayıklama işlevi olabilir, bu yüzden başka bir araç bu yaklaşımı kullanırsa, birlikte iyi oynayamazlar
  • Yeniden tanımla $PROMPT_COMMANDilk kanca işlevini çalıştırmak için. Etkileşimli olmayan mermilerde çalışmadığından ve başka bir araç bilgi istemi komutunu tanımladığında, birlikte iyi oynayamadıkları için bu yetersizdir.

Kısacası, eğer bash zshell'in chpwd_functionskancası gibi bir şey sağlamışsa, tek büyük çözüm gibi görünüyor, ama bunu doğru bir şekilde simüle etmek imkansız görünüyor.


1

Bakımcı cd tanımını değiştirmekten hoşlanmıyorsa, başka bir seçenek de bu dizin içi ortamı kullanan tüm komutları yeniden tanımlamak olacaktır:

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

PWD kancası ve dizin içi yapılandırma yalnızca gerektiğinde işleneceği için bu oldukça etkili olacaktır.

Örnek check_pwd işlevinizde değiştirebilirim:

my_function

için:

my_function "$PWD"

yeni cwd'yi geçmek için (daha modüler, test edilebilir olabilir).


"Bu dizin içi ortamı kullanan tüm komutları yeniden tanımlayın" Ne yazık ki, bunu tahmin edemiyorum.
Nathan Long

0

Dağıtımınıza göre inotify araçlarını kurun .

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

httpdÖrneğimde, belirtilen dizinde bir şey değişirse (Değiştir, Oluştur, Sil) aşağıdaki komut yeniden başlatılır .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.