Come posso verificare se esiste un'applicazione in $ PATH?


19

Sto provando a scrivere tutti i miei shscript di avvio / env per lavorare con il maggior numero di DRY e il più possibile: "funziona su ogni * nix in cui lo clono", per quanto possibile. Ciò significa assicurarsi che se provo a eseguire il codice che non è presente, il codice non riesce correttamente. A tal fine, devo essere in grado di verificare se esistono programmi. So come verificare se esiste un file, ma non sono sicuro di come verificare se un'applicazione è eseguibile all'interno del percorso. Preferirei usare $ PATH, poiché alcuni di questi devono funzionare su arch, ubuntu e centos. Alcuni potrebbero essere installati nel mio homedir, su sistemi in cui non ho root, altri potrebbero non essere installati e altri ancora potrebbero essere installati nei percorsi di sistema.


2
Questa risposta SO è quella che ho aggiunto ai segnalibri per tali domande.
jw013,

Risposte:


19

Usa type commandname. Questo restituisce vero se commandnameè qualcosa eseguibile: alias, funzione, comando incorporato o esterno (cercato in $PATH). In alternativa, utilizzare ciò command commandnameche restituisce true se si commandnametratta di un comando incorporato o esterno (cercato in $PATH).

exists () {
  type "$1" >/dev/null 2>/dev/null
}

Ci sono alcune varianti sh (sicuramente pre-POSIX; lo so /bin/shsotto OSF1 ≤3.x e alcune versioni della shell Almquist trovate nelle prime versioni di NetBSD e alcune distribuzioni Linux del 20 ° secolo) dove typerestituisce sempre 0 o no esistere. Non credo che nessun sistema sia stato spedito con questi in questo millennio. Se mai li incontri, ecco una funzione che puoi usare per cercare $PATHmanualmente:

exists () { (
    IFS=:
    for d in $PATH; do
      if test -x "$d/$1"; then return 0; fi
    done
    return 1
) }

Questa funzione è generalmente utile se si desidera escludere incorporati e funzioni e cercare il nome in $PATH. La maggior parte delle shell ha un built-in per questo, command -vsebbene sia un'aggiunta relativamente recente a POSIX (ancora opzionale a partire da POSIX: 2004). È fondamentalmente una versione di programmazione per type: stampa il percorso completo per un eseguibile in $PATH, il nome nudo per un built-in o una funzione e una definizione alias per un alias.

exists_in_path () {
  case $(command -v -- "$1") in
    /*) return 0;;
    alias\ *) return 1;; # alias
    *) return 1;; # built-in or function
  esac
}

Ksh, bash e zsh devono anche type -pcercare solo gli eseguibili in $PATH. Si noti che in bash, lo stato di ritorno di type -p fooè 0 se fooè un built-in o una funzione; se si desidera verificare un eseguibile in $PATH, è necessario verificare che l'output non sia vuoto. type -pnon è in POSIX; per esempio la cenere di Debian (che si trova /bin/shsu Ubuntu) non ce l'ha.


@gilles, questo (o qualcosa di simile) if [ type keychain ]; thennon funzionerà? Ottengo l'errore /home/xenoterracide/.zshrc:84: parse error: condition expected: typesuppongo di poter scrivere la funzione esiste ... Ho pensato che potesse essere più semplice in un certo senso ...
xenoterracide

@xenoterracide: rilasciare le parentesi!
Gilles 'SO- smetti di essere malvagio' il

Penso che tu stia cercando if type $APP >/dev/null 2>/dev/null; then ...Non vuoi il [].
Steven D,

4
Bah, sapevo che avrei dovuto rinfrescarmi. Picchiato di nuovo da Gilles!
Steven D,

type -pse stai specificatamente cercando un comando $PATH(non alias o funzioni o builtin).
effimero

1

Se stai cercando solo programmi esterni, puoi anche usare quale. Non so quanto sia portatile.


3
In teoria, è meno portatile di typeo command; whichnon è in POSIX, ad esempio. In pratica, whichesiste quasi ovunque, ma in alcuni punti (dove è implementato come uno script csh) usa un percorso diverso (a causa di a .cshrc), che sconfigge lo scopo.
Gilles 'SO- smetti di essere malvagio' il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.