Başarıya kadar bash'da bir komutu nasıl çalıştırabilirsiniz?


237

Bir komut dosyası var ve kullanıcıdan bazı bilgiler istemek istiyorum, kullanıcı bu bilgileri dolduruncaya kadar komut dosyası devam edemez. Aşağıdaki, bunu başarmak için bir döngü içine bir komut koymak için benim girişimdir, ancak bir nedenle işe yaramıyor.

echo "Please change password"
while passwd
do
echo "Try again"
done

While döngüsünün birçok varyasyonunu denedim:

while `passwd`
while [[ "`passwd`" -gt 0 ]]
while [ `passwd` -ne 0 ]]
# ... And much more

Ama işe yaramaz gibi gözükmüyorum.

Yanıtlar:


403
until passwd
do
  echo "Try again"
done

veya

while ! passwd
do
  echo "Try again"
done

20
Bu Ctrl-C için zor.
DonGar

Bunu iptal etmeniz gerektiğini düşünüyorsanız, kabuğunuzun yeni bir örneğini açın (örneğin, "bash" yazın) ve iptal etmek istediğinizde başka bir terminal penceresine gidin ve yeni ortaya çıkan bash'ı öldürün süreci.
Ethan

50
Bunun dışında Ctr-C yapmak kolaydır: until passwd; do echo "Try again"; sleep 2; done- tek yapmanız gereken iş yaptıktan hemen sonra (verilen iki saniye içinde) Ctr-C'ye basmaktır echo.
Christian

9
@azmeuk: Şöyle bir şey deneyin until passwd || (( count++ >= 5 )); do echo "foo"; done(yalnızca bash, bu değişken varsa sayıyı 0 olarak ayarladığınızdan emin olun) Düz sh için buna ihtiyacınız varsa, vücuttaki sayacı
artırın

2
Bu sayfaya defalarca başvurduktan
felipou

94

Bunun $?yerine bir önceki komutun çıkış durumu olan sınamanız gerekir . passwdher şey yolunda giderse 0 ile ve şifre değişikliği başarısız olursa sıfırdan çıkar (yanlış şifre, şifre uyuşmazlığı vb.)

passwd
while [ $? -ne 0 ]; do
    passwd
done

Backtick sürümünüzle, passwd'nin çıktısını karşılaştırıyorsunuz, ki bu Enter passwordve benzeri şeyler olacak confirm password.


2
Olmamalı mı $??
Shawn Chin

Bunu beğendim çünkü zıt duruma nasıl uyarlanacağı açık. örn. başarısız olana kadar deterministik olmayan bir hata ile bir program çalıştırın
Eric

Başarı sıfır olmayan bir çıkış kodu ile belirtildiğinde, ihtiyacınız olan şey budur.
Gudlaugur Egilsson

2
Bu biraz ilk değiştirerek üzerine geliştirilebilir düşünmek passwdile /bin/falsebazı uzun ve karmaşık komut size iki sürümünü tutmak istemiyorum varsa.
coladict

Kabul edilen cevap imho olmalıdır. Bu, çoğu kabukta (bash, mksh ve külle test edilmiştir) çalışmalıdır ve duruma kolayca uyarlanabilir.
linuxandria

73

@Marc B'nin cevabını detaylandırmak için,

$ passwd
$ while [ $? -ne 0 ]; do !!; done

Komuta özgü olmayan aynı şeyi yapmanın güzel bir yoludur.


11
Ne yazık ki benim için çalışmıyor ('!!' komutu bulunamadı). Nasıl çalışması gerekiyor?
Johannes Rudolph

2
Önceki komutu çalıştırmak bash numaradır. Örneğin sudo, bir komutun önüne yazmayı unutursanız sudo !!, önceki komutu kök ayrıcalıklarıyla çalıştırmak için yapmanız yeterlidir .
JohnEye

1
profilimde bunu yapabilen bir komut dosyası yapabilir miyim, böylece gidebilirim: $
makelastwork

2
Koşular arasında nasıl uyulur?
Kamil Dziedzic

6

Bunu başarmak için sonsuz bir döngü kullanabilirsiniz:

while true
do
  read -p "Enter password" passwd
  case "$passwd" in
    <some good condition> ) break;;
  esac
done

2
Çok satırlı komutumu bir fonksiyona koymayı gerektirmeyen tek cevap bu. && breakDoğrulama komutumdan sonra select olayı yerine yaptım .
carlin.scott

4

Yeniden deneme sınırına sahip olmak isteyen biri varsa:

max_retry=5
counter=0
until $command
do
   sleep 1
   [[ counter -eq $max_retry ]] && echo "Failed!" && exit 1
   echo "Trying again. Try #$counter"
   ((counter++))
done

1
until $(command)temelde her zaman yanlıştır. until commandBunun yerine kullanın . $(...)Neden çıktı ait commandkendisi bir komut olarak çalışacak olması ve çıkış durumu ikincil komuta döngü çalıştırmak veya başarısız karar ne olmaya; ancak stdout yoksa , komutun değiştirilmesi durumunda komutun kendisinin çıkış durumunun dikkate alınması gerekir.
Charles Duffy

$commandharika bir yer tutucu da değildir - komutları saklamak için dizelerin kullanılmasının neden güvenilmez olduğuna ilişkin BashFAQ # 50'ye bakın . Yine de, bu olduğundan daha iyi; aşağı oy geri çekildi.
Charles Duffy

3
while [ -n $(passwd) ]; do
        echo "Try again";
done;

3
Bunu yapmanın yolu bu değil ... psswd stdoutunu reddediyor ve daha sonra üzerinde tek bir test yapıyorsunuz. @duckworthd iyidir.
Ray Foss

Üstelik alıntı değil olduğundan, test var ne zaman yaramazlık gidiyor olduğunu çıkışı ancak birden fazla kelime ya da bu maçları geçerli dizinde dosyaları veya benzeri bir topak ifadesidir.
Charles Duffy
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.