Bagaimana saya menguji untuk melihat apakah ada aplikasi di $ PATH?

19

Saya mencoba untuk menulis semua shskrip startup / env saya untuk bekerja dengan KERING sebanyak dan sebanyak: "bekerja pada setiap * nix saya mengkloning ke", mungkin. Ini berarti memastikan bahwa jika saya mencoba menjalankan kode yang tidak ada di sana, kode itu gagal dengan anggun. Untuk itu saya harus bisa menguji apakah ada program. Saya tahu cara menguji apakah ada file, tetapi saya tidak yakin cara menguji untuk melihat apakah suatu aplikasi dapat dieksekusi di dalam path. Saya lebih suka menggunakan $ PATH, karena beberapa di antaranya perlu bekerja di arch, ubuntu, dan centos. Beberapa mungkin diinstal di homedir saya, pada sistem di mana saya tidak memiliki root, yang lain mungkin tidak diinstal, dan yang lain saya diinstal di jalur sistem.

xenoterracide
sumber
2
Ini jawabannya SO adalah yang saya telah bookmarked untuk pertanyaan seperti itu.
jw013

Jawaban:

19

Gunakan type commandname. Ini mengembalikan true jika commandnameada sesuatu yang dapat dieksekusi: alias, fungsi, built-in atau perintah eksternal (melihat ke atas $PATH). Atau, gunakan command commandnameyang mengembalikan true jika commandnameadalah perintah bawaan atau eksternal (lihat ke atas $PATH).

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

Ada beberapa varian sh (pasti pra-POSIX; Saya tahu di /bin/shbawah OSF1 ≤3.x dan beberapa versi shell Almquist ditemukan di versi NetBSD awal dan beberapa distribusi Linux abad ke-20) di mana typeselalu mengembalikan 0 atau tidak ada. Saya tidak berpikir ada sistem yang dikirim dengan milenium ini. Jika Anda pernah menjumpainya, berikut adalah fungsi yang dapat Anda gunakan untuk mencari $PATHsecara manual:

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

Fungsi ini umumnya berguna jika Anda ingin mengecualikan built-in dan fungsi dan mencari nama di $PATH. Sebagian besar shell memiliki built-in untuk ini, command -vmeskipun ini merupakan tambahan yang relatif baru untuk POSIX (masih opsional pada POSIX: 2004). Ini pada dasarnya versi ramah-programmer type: ia mencetak path lengkap untuk dieksekusi di $PATH, nama telanjang untuk built-in atau fungsi, dan definisi alias untuk alias.

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

Ksh, bash dan zsh juga harus type -pmencari yang hanya dapat dieksekusi di $PATH. Perhatikan bahwa dalam bash, status pengembalian type -p fooadalah 0 jika foomerupakan built-in atau fungsi; Jika Anda ingin menguji untuk dieksekusi di $PATH, Anda perlu memeriksa bahwa output tidak kosong. type -ptidak dalam POSIX; misalnya abu Debian (yang ada /bin/shdi Ubuntu) tidak memilikinya.

Gilles 'SANGAT berhenti menjadi jahat'
sumber
@ gilles, apakah ini (atau yang serupa) if [ type keychain ]; thentidak berfungsi? Saya mendapatkan kesalahan /home/xenoterracide/.zshrc:84: parse error: condition expected: typeSaya kira saya bisa menulis fungsi ada ... Saya hanya berpikir ini mungkin lebih sederhana dalam arti ...
xenoterracide
@xenoterracide: Jatuhkan kurung!
Gilles 'SO- stop being evil'
Saya pikir Anda sedang mencari if type $APP >/dev/null 2>/dev/null; then ...Anda tidak ingin [].
Steven D
4
Bah, aku tahu aku seharusnya menyegarkan. Dipukuli oleh Gilles lagi!
Steven D
type -pjika Anda secara khusus mencari perintah di $PATH(bukan alias atau fungsi atau bawaan).
ephemient
1

Jika Anda hanya mencari program eksternal, Anda juga dapat menggunakannya. Tidak tahu seberapa portabel itu.

Kim
sumber
3
Secara teori, ini kurang portabel daripada typeatau command; whichtidak ada dalam POSIX, misalnya. Dalam praktiknya, whichmemang ada hampir di mana-mana, tetapi di beberapa tempat (di mana itu diterapkan sebagai skrip csh) ia menggunakan jalur yang berbeda (karena a .cshrc), yang mengalahkan tujuannya.
Gilles 'SO- stop being evil'