Hoe kan ik voorwaardelijk iets doen als een commando is geslaagd of mislukt

Hoe kan ik zoiets doen in bash?

if "`command` returns any error"; then echo "Returned an error" else echo "Proceed..." fi 

Antwoord

Hoe je voorwaardelijk iets kunt doen als een commando is geslaagd of mislukt

Dat is precies wat bash “s if statement doet:

if command ; then echo "Command succeeded" else echo "Command failed" fi 

Informatie uit reacties toevoegen: je don” t moet in dit geval de [] syntaxis gebruiken. [ is zelf een commando, bijna gelijk aan test. Het is waarschijnlijk het meest gebruikte commando in een if, wat kan leiden in de veronderstelling dat het deel uitmaakt van de syntaxis van de shell. Maar als je wilt testen of een commando geslaagd is of niet, gebruik het commando zelf dan direct met if, zoals hierboven getoond.

Opmerkingen

  • Merk op dat de puntkomma belangrijk is.
  • Of je kunt then op een aparte regel zetten.
  • @Joe: ik denk dat je if ! command ; then ... ; fi bedoelt. [ is zelf een commando, en het ‘ is in dit geval niet nodig.
  • @Joe: My way heeft ook de deugd correct te zijn. if [ ! command ] wordt niet ‘ uitgevoerd command; het behandelt command als een string en behandelt het als waar omdat het een lengte heeft die niet nul is. [ is een synoniem voor het test commando
  • Oeps. Je ‘ heeft het correct.

Antwoord

Voor kleine dingen die je wilt laten gebeuren als een shell-commando werkt, kun je het && construct gebruiken:

rm -rf somedir && trace_output "Removed the directory" 

Evenzo voor kleine dingen die u wilt laten gebeuren als een shell-commando mislukt, kunt u ||:

rm -rf somedir || exit_on_error "Failed to remove the directory" 

of beide gebruiken

rm -rf somedir && trace_output "Removed the directory" || exit_on_error "Failed to remove the directory" 

Het is waarschijnlijk onverstandig om veel met deze constructies te doen, maar ze kunnen bij gelegenheid de stroom van controle een stuk duidelijker maken.

Reacties

  • Ze zijn korter en (tenminste in sommige shells) sneller. Ik huiver als ik me een monster Ultrix-installatiescript herinner dat is geschreven met alleen deze voorwaardelijke constructies die ik ooit heb geprobeerd ontcijferen …

Antwoord

Controleer de waarde van $?, dat het resultaat bevat van het uitvoeren van de meest recente opdracht / functie:

#!/bin/bash echo "this will work" RESULT=$? if [ $RESULT -eq 0 ]; then echo success else echo failed fi if [ $RESULT == 0 ]; then echo success 2 else echo failed 2 fi 

Reacties

  • Hoewel het technisch correct is (en dus geen downvote rechtvaardigt), is het ‘ s maakt geen gebruik van Bash ‘ s if idioom. Ik geef de voorkeur aan Keith Thompson ‘ s antwoord.
  • Er zijn voordelen aan dit idioom – het behoudt de geretourneerde waarde. Al met al vind ik deze krachtiger, hoewel meer uitgebreid. het ‘ is ook gemakkelijker te lezen.
  • Wat is ” Bash ‘ s if idiom “?
  • @Nowaker Het feit dat het enige doel van if is om te doen dit. De flow control voorwaarden in Bash onderzoeken allemaal $? achter de schermen; dat ‘ is wat ze doen. Het expliciet onderzoeken van de waarde ervan zou in de overgrote meerderheid van de gevallen niet nodig moeten zijn, en is meestal een antipatroon voor beginners.
  • Ik geef hier de voorkeur aan vanwege de leesbaarheid. Het hoofdcommando is meestal erg lang. Door het in een ” te plaatsen als ” -instructie slecht leesbaar is.

Antwoord

Dit werkte voor mij:

command && echo "OK" || echo "NOK" 

if command slaagt, wordt echo "OK" uitgevoerd, en aangezien het succesvol is, stopt de uitvoering daar. Anders wordt && overgeslagen, en echo "NOK" wordt uitgevoerd.

Opmerkingen

  • Als je iets wilt doen als het mislukt, en bewaar de afsluitcode (om te tonen in opdrachtprompt of test in een script), u kunt dit doen: command && echo "OK" || c=$?; echo "NOK"; $(exit $c)
  • @ Sam-Hasler: shouldn ‘ t dat command && echo "OK" || (c=$?; echo "NOK"; (exit $c))?
  • En als het echo "OK" -gedeelte zichzelf mislukt, dan is dit beter: command && (echo "OK"; exit 0) || (c=$?; echo "NOK"; (exit $c))
  • @ jrw32982, Nice, ik ‘ heb de vorige constructie gebruikt, maar niet het laatste.
  • Het echte antwoord staat in de reacties, allemaal bedankt!

Antwoord

Opgemerkt moet worden dat if...then...fi en && / || type benadering behandelt de exitstatus die wordt geretourneerd door het commando dat we willen testen (0 bij succes); sommige commandos geven echter geen exit-status die niet gelijk is aan nul als het commando is mislukt of de invoer niet kon verwerken. Dit betekent dat de gebruikelijke if en && / || benaderingen niet werken voor die bepaalde commandos.

Onder Linux wordt bijvoorbeeld GNU file nog steeds afgesloten met 0 als het een niet-bestaand bestand als argument heeft ontvangen en find kon het door de gebruiker opgegeven bestand niet vinden.

$ find . -name "not_existing_file" $ echo $? 0 $ file ./not_existing_file ./not_existing_file: cannot open `./not_existing_file" (No such file or directory) $ echo $? 0 

In dergelijke gevallen is een mogelijke manier om met de situatie om te gaan, het lezen van stderr / stdin berichten, bijv. degenen die zijn geretourneerd door file commando, of de uitvoer van het commando ontleden zoals in find. Voor dat doel zou een case instructie kunnen worden gebruikt.

$ file ./doesntexist | while IFS= read -r output; do > case "$output" in > *"No such file or directory"*) printf "%s\n" "This will show up if failed";; > *) printf "%s\n" "This will show up if succeeded" ;; > esac > done This will show up if failed $ find . -name "doesn"texist" | if ! read IFS= out; then echo "File not found"; fi File not found 

Antwoord

De meest foutgevoelige die ik kon bedenken was:

  • Haal eerst de waarde. Stel dat u iets doet als:

RR=$?

Nu, niet alleen voor deze situatie, maar ook voor andere situaties waarmee u te maken kunt krijgen, overweeg:

gedefinieerde variabele:

$ AA=1 ; if (( "10#0${AA}" == 1 )) ; then echo yes ; else echo no ; fi

Antwoord: ja

$ AA=1 ; if (( "10#0${AA}" != 1 )) ; then echo yes ; else echo no ; fi

Antwoord: nee

ongedefinieerde variabele:

$ AA=1 ; if (( "10#0${BB}" == 1 )) ; then echo yes ; else echo no ; fi

Antwoord: nee

$ AA=1 ; if (( "10#0${BB}" != 1 )) ; then echo yes ; else echo no ; fi

Antwoord: ja

$ AA=1 ; if (( "10#0${BB}" == 0 )) ; then echo yes ; else echo no ; fi

Antwoord: ja

Dit voorkomt allerlei soorten fouten.

U kent waarschijnlijk alle syntaxis, maar hier enkele tips:

  • Gebruik aanhalingstekens. Voorkom dat "blank" nothing is.
  • De nieuwe moderne notatie voor variabelen is ${variable}.
  • Het toevoegen van een nul aaneengeschakeld voor uw nummer, vermijdt ook “helemaal geen nummer”.
  • Maar wacht even, als u een nul toevoegt, wordt het nummer base-8. U krijgt een foutmelding als:
    • value too great for base (error token is "08") voor getallen boven 7. Dat is wanneer 10# in het spel komt:
    • 10# dwingt het getal .

Antwoord

Je kunt dit doen:

if ($( ping 4.4.4.4 -c1 > /dev/null )) ; then echo "ping response succsess!!!" fi 

Reacties

  • Dat werkt, maar is ingewikkeld. U ‘ voert ping uit in een subshell van een subshell, de uitvoer van ping wordt vastgelegd om het als een commando uit te voeren. Maar omdat de uitvoer wordt omgeleid naar / dev / null, zal dat altijd de lege string zijn. Dus je ‘ voert niets uit in een subshell, wat betekent dat de vorige exit-status (van de commandosubstitutiesubshell, dat wil zeggen van ping) behouden blijft. Het is duidelijk dat de juiste manier if ping ...; then hier is.

Antwoord

Zoals elders in deze thread opgemerkt, beantwoordt de oorspronkelijke vraag in feite zichzelf. Hier is een illustratie die laat zien dat if voorwaarden ook kunnen worden genest.

In dit voorbeeld wordt if gebruikt om te controleren of een bestand bestaat en of het een gewoon bestand is. Als deze voorwaarden waar zijn, controleer dan of het een grootte heeft groter dan 0.

#!/bin/bash echo "Which error log are you checking today? " read answer if [ -f /opt/logs/$answer*.errors ] then if [ -s /opt/logs/$answer*.errors ] then echo "Content is present in the $answer error log file." else echo "No errors are present in the $answer error log file." fi else echo "$answer does not have an error log at this time." fi 

Reacties

  • Dat is wat je antwoord doet, maar je antwoord behandelt de vraag niet.
  • @JeffSchaller, bedankt voor je opmerking. Ik heb mijn bericht bewerkt om een verwijzing naar de vraag op te nemen.

Antwoord

#!/bin/bash if command-1 ; then echo "command-1 succeeded and now running from this block command-2" command-2 else echo "command-1 failed and now running from this block command-3" command-3 fi 

Reacties

Antwoord

Dit kan eenvoudig op deze manier worden gedaan aangezien $? u de status geeft van de laatste uitgevoerde opdracht.

Dus het zou kunnen zijn

#!/bin/sh ... some command ... if [ $? == 0 ] ; then echo "<the output message you want to display>" else echo "<failure message>" fi 

Reacties

  • Downvote: dit is een parafrase van een eerder antwoord dat terecht kritiek heeft gekregen omdat het unidiomatisch is.
  • Eigenlijk was dit precies wat ik zocht omdat ik ‘ m probeer om het ” commando ” het script te laten mislukken als onderdeel van ” set -e ” wat het niet ‘ doet als het ‘ een deel van de if is.Dit mag niet ‘ worden neergeslagen.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *