Jak uruchomić polecenie i uzyskać kod wyjściowy w mniejszej liczbie znaków?

13

Pisałem swoje skrypty w ten sposób:

some_command
while [ $? -ne 0 ] ; do
    sleep 1
    some_command
done

Zawsze denerwowało mnie, że muszę pisać some_commanddwa razy. Czy mogę jakoś umieścić go w sekcji testu pętli?

Mihai
źródło

Odpowiedzi:

20

Możesz użyć some_commandjako warunek testu.

while ! some_command; do sleep 1; done

Warunek pozostanie prawdziwy, dopóki some_commandzakończy się z błędem.

Lub bardziej szczegółowy sposób, jeśli chcesz wykonać dodatkowe kontrole:

while ! some_command
do 
    # add more if desired
    sleep 1
done
John WH Smith
źródło
Wygląda to lepiej niż moje, chociaż jest to jedna linijka ;-)
Anthon
OP może chcieć podzielić go na kilka linii, gdyby musiał wykonać kilka poleceń po awarii :)
John WH Smith,
Nie ma powodu, dla którego nie można podzielić linii na średniki, aby uczynić ją wieloliniową.
Mark Stewart
1
... lub napiszwhile ! some_command; do several; commands; sleep 1; done
ignis
12

Do tego służy untilpętla:

until some_command
do    sleep 1
done

Jest to logiczna negacja whilepętli.

Specyfikacja mówi:

untilLoop

  • untilPętla nieprzerwanie wykonać jedną bezkonsolowe listy tak długo, jak inny związek, lista ma status wyjścia niezerową.

  • Format pętli till jest następujący:

    aż do listy złożonej-1
    wykonaj listę złożoną-2
    gotowy
  • Lista złożona-1 zostanie wykonana, a jeśli ma zerowy status wyjścia, untilpolecenie zostanie zakończone. W przeciwnym razie zostanie wykonana lista złożona-2 , a proces się powtórzy.
mikeserv
źródło
4

Możesz po prostu zrobić:

false
while [ $? -ne 0 ] ; do
   sleep 1
   some_command
done

ma to jednak tę wadę, że zawsze najpierw śpi jedną sekundę

Jeśli chcesz móc wyjść z dowolnej z komend, aby wyjść z 0, możesz:

while true; do
  if [ some_command ] ; then break ; fi
  if [ some_other_command ] ; then break ; fi
  sleep 1
done

co oczywiście działa również dla just some_command

Anthon
źródło
5
Drugi przykład nie powinien zawierać poleceń [i ]wokół nich.
nyuszika7h
2

Ani while ! ...nie until ...działa w systemach, które zamroziły środowisko powłoki przed POSIX.1-2001. Tak jednak się dzieje.

while :; do
    if some command; then
        break
    fi
    sleep 1
done

Jeśli nie potrzebujesz całkowitej przenośności, dlaczego piszesz skrypt powłoki? Bardziej prawdopodobne jest, że Perl będzie dostępny niż Bash.

sleep 1 while 0 != system qw(some command);

(Jak wyżej, wykonywana sleepjest tylko wtedy, gdy polecenie nie powiedzie się.)

zwol
źródło