Kaip patikrinti, ar programa yra iš „bash“ scenarijaus?

Kaip galiu patikrinti, ar yra programa, kuri sugrąžins klaidą ir išeis, arba toliau naudos scenarijų?

Atrodo, kad tai turėtų būti paprasta, bet mane sudaužė.

1748 m
27 февр. 27 gr . 2009-02-27 00:52 '09, 12:52 AM 2009-02-27 00:52
@ 35 atsakymai
  • 1
  • 2

Atsakymas

POSIX suderinamumas:

 command -v <the_command> 

bash konkrečiai aplinkai:

 hash <the_command> # For regular commands. Or... type <the_command> # To check built-ins and keywords 

Aprašymas

Venkite. Tai ne tik išorinis procesas, kurį atliekate labai mažai (tai reiškia, kad įmontuotos funkcijos, pvz., hash , type ar command yra daug pigesnės), taip pat galite pasikliauti integruotomis funkcijomis, kad iš tikrųjų atliktumėte tai, ko norite. pageidaujama, o išorinių komandų poveikis gali skirtis nuo sistemos.

Kodėl rūpintis?

  • Daugelis operacinių sistemų turi netgi išėjimo būsenos nustatymą , o tai reiškia, kad if which foo jis net neveikia, ir visada bus, kad foo egzistuoja, net jei tai nėra (atkreipkite dėmesį, kad kai kurie POSIX kevalai taip pat atrodo tai yra hash .
  • Daugelis operacinių sistemų daro which paprastą ir blogą, pvz., Keisti išvestį arba netgi prijungti prie paketo valdytojo.

Taigi nenaudokite, which . Vietoj to naudokite vieną iš šių būdų:

 $ command -v foo >/dev/null 2> || { echo > "I require foo but it not installed. Aborting."; exit 1; } $ type foo >/dev/null 2> || { echo > "I require foo but it not installed. Aborting."; exit 1; } $ hash foo 2>/dev/null || { echo > "I require foo but it not installed.  Aborting."; exit 1; } 

(Mažoji pastabos pusė: kai kurie mano, kad 2>> yra tas pats 2>/dev/null , bet trumpesnis neteisingas. 2>> uždaro FD 2, kuris sukelia klaidą programoje, kai bando rašyti stderrui kuris labai skiriasi nuo sėkmingo rašymo prie jo ir išmetimo (ir pavojingo!)

Jei jūsų maišos takelis yra /bin/sh , tada turėtumėte rūpintis, ką sako POSIX. type ir hash išėjimo kodai nėra gerai apibrėžti POSIX, o hash , kaip matote, sėkmingai baigia, kai komanda neegzistuoja (dar nepastebėta to type ). command išėjimo būsena yra gerai apibrėžta POSIX, todėl tai tikriausiai yra saugiausia naudoti.

Jei jūsų scenarijus naudoja bash , nors POSIX taisyklės nebėra svarbios, ir tiek type tiek hash tapo visiškai saugūs naudoti. type dabar -P norite ieškoti tik PATH , ir hash turi šalutinį poveikį, kurį komandos vieta bus išjungta (norint greičiau ieškoti kitą kartą, kai jį naudosite), o tai paprastai yra gera, nes tikriausiai tikrinate jo egzistavimą faktiškai jį naudoti.

Kaip paprastas pavyzdys, čia yra funkcija, kuri veikia, jei ji yra, kitaip date :

 gnudate() { if hash gdate 2>/dev/null; then gdate "$@" else date "$@" fi } 
2478
24 марта '09 в 15:45 2009-03-24 15:45 Atsakymą pateikė lhunath kovo 24 d. , 09:45 , 2009-03-24 15:45

Toliau pateikiamas nešiojamas būdas patikrinti, ar $PATH yra komandoje ir yra vykdoma:

 [ -x "$(command -v foo)" ] 

Pavyzdys:

 if ! [ -x "$(command -v git)" ]; then echo 'Error: git is not installed.' > exit 1 fi 
border=0

Tikrinimas reikalingas, nes „bash“ grąžina nevykdomąjį failą, jei $PATH nėra vykdomojo failo su šiuo pavadinimu.

Taip pat atkreipkite dėmesį, kad jei nepanaudotas failas, kurio pavadinimas yra toks pat kaip ir vykdomasis failas, jau anksčiau yra $PATH , brūkšnys grąžina pirmąjį, nors jis bus įvykdytas. Ši klaida pažeidžia POSIX standartą. [ Klaidos ataskaita ] [ Standartinis ]

Be to, tai nepavyks, jei komanda, kurios ieškote, buvo nustatyta kaip slapyvardis.

324
05 нояб. atsakymas pateikiamas nyuszika7h 05 lapkričio. 2014-11-05 17:33 '14, 17:33 2014-11-05 17:33

Sutinku su „lhunath“, kad nebūtų skatinamas jų naudojimas, o jo sprendimas yra puikus BASH vartotojams. Tačiau norint, kad būtų daugiau nešiojamų, turėtumėte naudoti command -v :

 $ command -v foo >/dev/null 2> || { echo "I require foo but it not installed. Aborting." > exit 1; } 

command suderinama su POSIX, žr. Čia dėl jos specifikacijos: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/command.html

Pastaba: type suderinamas su POSIX, tačiau type -P nėra.

194
24 янв. atsakymą pateikė GregV 24 sausis 2011-01-24 21:16 '11, 21:16, 2011-01-24 21:16

Turiu funkciją, apibrėžtą mano .bashrc programoje, kuri palengvina.

 command_exists () { type "$1"  /dev/null ; } 

Čia yra pavyzdys, kaip jis buvo naudojamas (iš mano .bash_profile .)

 if command_exists mvim ; then export VISUAL="mvim --nofork" fi 
83
14 окт. Josh Strater atsakymas spalio 14 d 2010-10-14 12:24 '10, 12:24, 2010-10-14 12:24

Tai priklauso nuo to, ar norite žinoti, ar ji yra viename iš $PATH kintamojo katalogų, ar žinote, ar ji yra absoliučia. Jei norite sužinoti, ar jis yra $PATH kintamajame, naudokite

 if which programname >/dev/null; then echo exists else echo does not exist fi 

kitaip naudoti

 if [ -x /path/to/programname ]; then echo exists else echo does not exist fi 

Peradresavimas į /dev/null/ pirmame pavyzdyje slopina which programos programą.

68
27 февр. Atsakymą pateikė svajonė 27 vasario mėn. 2009-02-27 01:01 '09 ne 1:01 2009-02-27 01:01

Įjungus „@lhunath“ ir „@GregV“ atsakymus, čia yra žmonių, kurie nori lengvai atlikti šį patikrinimą, kodą, if :

 exists() { command -v "$1" >/dev/null 2> } 

Štai kaip jį naudoti:

 if exists bash; then echo 'Bash exists!' else echo 'Your system does not have Bash' fi 
30
08 дек. atsakymas, kurį pateikė Romário 08 dec. 2015-12-08 00:17 '15 - 0:17 2015-12-08 00:17

Pabandykite naudoti:

 test -x filename 

arba

 [ -x filename ] 

Bazinio žmogaus puslapyje Sąlyginės išraiškos :

  -x file True if file exists and is executable. 
20
27 февр. atsakymas ddckee 27 vasaris 2009-02-27 00:57 '09 0:57 2009-02-27 00:57

Jei norite naudoti „ hash , kaip rodo @lhunath , „bash“ scenarijuje:

 hash foo  /dev/null if [ $? -eq 1 ]; then echo > "foo not found." fi 

Šis scenarijus veikia hash ir tada patikrina, ar naujausios komandos išėjimo kodas yra $? saugoma vertė $? , lygus 1 . Jei hash nerandate foo , išėjimo kodas yra 1 . Jei foo , išėjimo kodas yra 0 .

/dev/null nukreipia standartinę klaidą ir standartinę išvestį iš hash , kad jis nebūtų rodomas ekrane, o echo >> rašo pranešimą į standartinę klaidą.

15
24 июня '11 в 20:01 2011-06-24 20:01 atsakymas pateikiamas „ dcharles“ birželio 24 d. 11 val. 20:01 2011-06-24 20:01

Niekada negavau pirmiau minėtų sprendimų darbui su >

 if [ `builtin type -p vim` ]; then echo "TRUE"; else echo "FALSE"; fi 
8
11 июля '09 в 21:38 2009-07-11 21:38 atsakymą pateikė Magnus liepos 11 d., 09:21, 2009-07-11 21:38

Patikrinkite, ar nėra daug priklausomybių ir ataskaitos būsenos galutiniams vartotojams.

 for cmd in latex pandoc; do printf '%-10s' "$cmd" if hash "$cmd" 2>/dev/null; then echo OK else echo missing fi done 

Pavyzdžio išvestis:

 latex OK pandoc missing 

Nustatykite 10 maksimalaus komandų ilgio. Ne automatinis, nes nematau „POSIX“ nežodinio būdo tai padaryti: Kaip išlyginti atskirtos lentelės stulpelius „Bash“?

7
23 марта '14 в 13:09 2014-03-23 13:09 atsakymas, kurį pateikė Ciro Santilli 改造 改造 中心 六四 法轮功 法轮功 Kovo 23, 14, 13:09 2014-03-23 ​​13:09

Jei patikrinate programos egzistavimą, tikriausiai ketinate ją paleisti vėliau. Kodėl gi ne bandyti paleisti jį pirmiausia?

 if foo --version >/dev/null 2> then echo Found else echo Not found fi 

Tai patikimesnis patikrinimas, ar programa veikia, o ne tik peržiūrėti PATH katalogus ir failų leidimus.

Be to, galite gauti naudingą rezultatą iš savo programos, pavyzdžiui, jos versiją.

Žinoma, trūkumai yra tai, kad kai kurias programas gali būti sunku paleisti, o kai kurios jų neturi --version parinkties, kad būtų galima iš karto (ir sėkmingai) išeiti.

7
08 июля '13 в 18:14 2013-07-08 18:14 atsakymas pateikiamas 0xF liepos 08 d. 13 val. 14:14 2013-07-08 18:14

hash foo 2>/dev/null : veikia su zsh, bash, brūkšneliais ir pelenais.

type -p foo : jis veikia su zsh, bash ir pelenais (busybox), bet ne brūkšniu (jis interpretuoja -p kaip argumentą).

command -v foo : veikia su zsh, bash, brūkšneliais, bet ne pelenais (busybox) ( -ash: command: not found ).

Taip pat atkreipkite dėmesį, kad builtin nėra su ash ir dash .

6
21 июля '14 в 3:13 2014-07-21 03:13 atsakymas pateikiamas „ mėlynasliepos 21 d . 14 val

Kodėl negalite naudoti įmontuotų „Bash“ funkcijų, jei galite?

 which programname 

...

 type -P programname 
6
24 марта '09 в 14:23 2009-03-24 14:23 atsakymas yra duotas kovo 24 d., 09:23, 2009-03-24 14:23

Jei norite atrasti įdiegtą biblioteką, suinteresuotiems asmenims nė viena iš pirmiau išvardytų metodikų neveikia. Manau, kad jūs turite tik fiziškai patikrinti kelią (galbūt antraštės failams ir pan.), Arba kažką panašaus (jei naudojate Debian'o pagrindą):

 dpkg --status libdb-dev | grep -q not-installed if [ $? -eq 0 ]; then apt-get install libdb-dev fi 

Kaip matyti iš pirmiau, atsakymas „0“ iš užklausos reiškia, kad paketas nėra įdiegtas. Ši funkcija "grep" - "0" reiškia atitikimą, "1" reiškia, kad nebuvo rastas atitikimas.

4
16 янв. Atsakymą pateikė Nathan Crause 16 sausis 2010-01-16 02:16 '10, 2:16, 2010-01-16 02:16

Kokia komanda gali būti naudinga. žmogus, kuris

Jei atkuriamas vykdomasis failas, jis grąžina 0, jei jis nerastas arba nepavyksta įvykdyti:

 NAME which - locate a command SYNOPSIS which [-a] filename ... DESCRIPTION which returns the pathnames of the files which would be executed in the current environment, had its arguments been given as commands in a strictly POSIX-conformant shell. It does this by searching the PATH for executable files matching the names of the arguments. OPTIONS -a print all matching pathnames of each argument EXIT STATUS 0 if all specified commands are found and executable 1 if one or more specified commands is nonexistent or not exe- cutable 2 if an invalid option is specified 

Geras dalykas yra tai, kad jis sužino, ar vykdomoji rinkmena yra prieinama aplinkoje, kurioje ji veikia - taupo kelias problemas ...

-Adam

3
27 февр. atsakymą pateikė Adam Davis , vasario 27 d. 2009-02-27 00:56 '09 ne 0:56 2009-02-27 00:56

Sakyčiau, kad nešiojamų ir 100% patikimų būdų nėra dėl alias pakabinimo. Pavyzdžiui:

 alias john='ls --color' alias paul='george -F' alias george='ls -h' alias ringo=/ 

Žinoma, tik pastaroji problema yra problemiška (jokio nusikaltimo Ringo!) Bet visi jie yra galiojantys alias command -v .

Norint atmesti pavargusį, pvz., „ ringo , turime išanalizuoti integruotos komandos pavadinimo išvestį ir pasikartoti į korpusą ( command -v neviršija alias ). Nėra jokio nešiojamojo sprendimo, o net „Bash“ specifinis sprendimas yra gana varginantis.

Atkreipkite dėmesį, kad šis sprendimas besąlygiškai atmeta alias ls='ls -F'

 test() { command -v $1 | grep -qv alias } 
3
10 марта '16 в 5:31 2016-03-10 05:31 atsakymas pateikiamas nodakai kovo 16 d. 16:31 val. 2016-03-10 05:31

Jei išorinio type komanda nepasiekiama (kaip įprasta čia ), galime naudoti su POSIX suderinamą env -i sh -c 'type cmd 1>/dev/null 2>> :

 # portable version of Bash type -P cmd (without output on stdout) typep() { command -p env -i PATH="$PATH" sh -c ' export LC_ALL=C > 

Ne mažiau kaip „Mac OS X 10.6.8“ naudojant „Bash 4.2.24“ (2) command -v ls neatitinka perkeltų /bin/ls-temp .

2
20 нояб. atsakymą pateikė freno lapkričio 20 d 2014-11-20 19:55 '14, 19:55, 2014-11-20 19:55

Čia yra daug variantų, bet nesu nustebęs, kai nebuvo greitų vieno eilutės simbolių, tai aš [[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1> exit 1; } [[ "$(command -v java)" ]] || { echo "java is not installed" 1> exit 1; } savo scenarijų pradžioje: [[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1> exit 1; } [[ "$(command -v java)" ]] || { echo "java is not installed" 1> exit 1; } [[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1> exit 1; } [[ "$(command -v java)" ]] || { echo "java is not installed" 1> exit 1; } [[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1> exit 1; } [[ "$(command -v java)" ]] || { echo "java is not installed" 1> exit 1; } [[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1> exit 1; } [[ "$(command -v java)" ]] || { echo "java is not installed" 1> exit 1; } [[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1> exit 1; } [[ "$(command -v java)" ]] || { echo "java is not installed" 1> exit 1; }

Tai pagrįsta čia pasirinktu atsakymu ir kitu šaltiniu (ir aš žaidžiau šiek tiek).

Tikiuosi, kad tai bus naudinga kitiems.

1
19 июня '18 в 15:02 2018-06-19 15:02 Atsakymą Keisar pateikė birželio 18 d. 18 val. 15:02 2018-06-19 15:02

Jei norite patikrinti, ar programa egzistuoja ir iš tikrųjų yra programa, o ne „bash“ integruota komanda , tada command , type ir hash nėra tinkamos bandymams, nes jie visi grąžina 0 išėjimo būseną integruotoms komandoms.

Pvz., Yra laiko programa, kuri siūlo daugiau funkcijų nei laiko . Jei norite patikrinti, ar programa egzistuoja, siūlyčiau naudoti, kaip, kaip nurodyta šiame pavyzdyje:

 # first check if the time program exists timeProg=`which time` if [ "$timeProg" = "" ] then echo "The time program does not exist on this system." exit 1 fi # invoke the time program $timeProg --quiet -o result.txt -f "%S %U + p" du -sk ~ echo "Total CPU time: `dc -f result.txt` seconds" rm result.txt 
1
19 июня '16 в 2:19 2016-06-19 02:19 atsakymas pateikiamas rpr birželio 16 d. 16:19 2016-06-19 02:19

Jei negalite dirbti aukštesnėje / žemesnėje padėtyje ir ištraukti plaukus iš nugaros, pabandykite atlikti tą pačią komandą naudodami bash -c . Pažvelkite į šį abejotiną nesąmonę, tai iš tikrųjų atsitinka, kai veikia $ (sub-command):

Visų pirma. Tai gali suteikti jums visiškai kitokį kelią.

 $ command -v ls alias ls='ls --color=auto' $ bash -c "command -v ls" /bin/ls 

Antra. Jis negali jums pateikti jokių išvadų.

 $ command -v nvm nvm $ bash -c "command -v nvm" $ bash -c "nvm --help" bash: nvm: command not found 
1
26 авг. atsakymas, kurį pateikė vartotojo619271 rugpjūčio 26 d. 2015-08-26 12:23 '15 , 12:23 val. 2015-08-26 12:23

mano debiano serverio sąranka. Turiu problemų, kai keli paketai turi tą patį pavadinimą. pavyzdžiui, apache2. taigi tai buvo mano sprendimas.

 function _apt_install() { apt-get install -y $1 > /dev/null } function _apt_install_norecommends() { apt-get install -y --no-install-recommends $1 > /dev/null } function _apt_available() { if [ `apt-cache search $1 | grep -o "$1" | uniq | wc -l` = "1" ]; then echo "Package is available : $1" PACKAGE_INSTALL="1" else echo "Package $1 is NOT available for install" echo "We can not continue without this package..." echo "Exitting now.." exit 0 fi } function _package_install { _apt_available $1 if [ "${PACKAGE_INSTALL}" = "1" ]; then if [ "$(dpkg-query -l $1 | tail -n1 | cut -c1-2)" = "ii" ]; then echo "package is already_installed: $1" else echo "installing package : $1, please wait.." _apt_install $1 sleep 0.5 fi fi } function _package_install_no_recommends { _apt_available $1 if [ "${PACKAGE_INSTALL}" = "1" ]; then if [ "$(dpkg-query -l $1 | tail -n1 | cut -c1-2)" = "ii" ]; then echo "package is already_installed: $1" else echo "installing package : $1, please wait.." _apt_install_norecommends $1 sleep 0.5 fi fi } 
1
27 марта '15 в 17:26 2015-03-27 17:26 atsakymas duotas ThCTLo kovo 27 d. 15 val. 17:26 2015-03-27 17:26

„Hash“ variante yra viena klaida: komandinėje eilutėje galite, pavyzdžiui, įvesti

 one_folder/process 

užbaigti procesą. Norėdami tai padaryti, tėvų aplankas one_folder turi būti $ PATH. Bet kai bandysite išgauti šią komandą, ji visada bus sėkminga:

 hash one_folder/process; echo $? # will always output '0' 
1
14 дек. atsakymas pateikiamas anycast.cw 14 d. 2011-12-14 15:41 '11, 15:41, 2011-12-14 15:41

Norint imituoti Bash type -P cmd , galime naudoti su POSIX suderinamą env -i type cmd 1>/dev/null 2>> .

 man env # "The option '-i' causes env to completely ignore the environment it inherits." # In other words, there are no aliases or functions to be looked up by the type command. ls() { echo 'Hello, world!'; } ls type ls env -i type ls cmd=ls cmd=lsx env -i type $cmd 1>/dev/null 2> || { echo "$cmd not found"; exit 1; } 
1
01 июня '11 в 20:49 2011-06-01 20:49 atsakymas suteiktas tim 01 Jun '11, 20:49 2011-06-01 20:49

„-V“ komanda veikia gerai, jei parametras POSC_BUILTINS nustatytas parametrams <command> , tačiau jis gali nepavykti, jei ne. (jis dirbo man daugelį metų, bet neseniai atėjo, kur jis neveikė).

Manau, kad šie duomenys yra patikimesni:

 test -x $(which <command>) 

Kadangi ji tikrina 3 dalykus: kelią, egzistavimą ir leidimą atlikti.

1
25 июня '18 в 19:53 2018-06-25 19:53 atsakymas duotas AnthonyC birželio 25 d. 18 val

Priklausomai nuo vietos, jis jums pasakys, ar programa egzistuoja.

 if [ -x /usr/bin/yum ]; then echo This is Centos fi 
1
27 нояб. Atsakymą pateikė Klevin Kona 27 lapkritis. 2018-11-27 19:03 '18, 19:03 2018-11-27 19:03

Antra, naudokite komandą -v. Pavyzdžiui. pavyzdžiui:

 md=$(command -v mkdirhier) ; alias md=${md:=mkdir} # bash emacs="$(command -v emacs) -nw" || emacs=nano alias e=$emacs [[ -z $(command -v jed) ]]  alias jed=$emacs 
1
06 нояб. atsakymą pateikė vartotojo2961933 06 lapkritis. 2013-11-06 22:06 '13, 22:06 pm 2013-11-06 22:06

Aš naudoju, nes tai labai paprasta:

 if [ `> 

arba

 if [ `> 

Jis naudoja korpuso ir programinės įrangos echo būseną stdout ir nieko stderr, kita vertus, jei komanda nerandama, ji turi echos statusą tik stderr.

0
22 сент. Atsakymas pateiktas AN 22 rugsėjo. 2015-09-22 03:41 '15, 03:41 am 2015-09-22 03:41

Scenarijaus

 #!/bin/bash # Commands found in the hash table are checked for existence before being # executed and non-existence forces a normal PATH search. shopt -s checkhash function exists() { local mycomm=$1; shift || return 1 hash $mycomm 2>/dev/null || \ printf "\xe2\x9c\x98 [ABRT]: $mycomm: command does not exist\n"; return 1; } readonly -f exists exists notacmd exists bash hash bash -c 'printf "Fin.\n"' 

Rezultatas

 ✘ [ABRT]: notacmd: command does not exist hits command 0 /usr/bin/bash Fin. 
0
06 сент. atsakymas duotas ekwpz91 06 sep . 2017-09-06 03:42 '17 at 3:42 2017-09-06 03:42
 GIT=/usr/bin/git # STORE THE RELATIVE PATH # GIT=$(which git) # USE THIS COMMAND TO SEARCH FOR THE RELATIVE PATH if [[ ! -e $GIT ]]; then # CHECK IF THE FILE EXISTS echo "PROGRAM DOES NOT EXIST." exit 1 # EXIT THE PROGRAM IF IT DOES NOT fi # DO SOMETHING ... exit 0 # EXIT THE PROGRAM IF IT DOES 
-1
16 апр. Da'Jour atsakymas, pateiktas balandžio 16 d 2017-04-16 04:21 '17 at 4:21 2017-04-16 04:21

Turėjau patikrinti, ar „ git buvo įdiegta kaip mūsų CI serverio diegimo dalis. Mano paskutinis „bash“ scenarijus buvo toks (Ubuntu serveris):

 if ! builtin type -p git  then sudo apt-get -y install git-core fi 

Tikiuosi, kad tai padės kitam!

-1
08 апр. Greg K 08 d. atsakymas . 2011-04-08 18:30 '11, 18:30, 2011-04-08 18:30
  • 1
  • 2

Kiti klausimai apie „ žymes arba „ Užduoti klausimą“