Pertanyaan Bagaimana cara memeriksa apakah ada program dari skrip Bash?


Bagaimana saya akan memvalidasi bahwa ada program, dengan cara yang akan mengembalikan kesalahan dan keluar, atau melanjutkan dengan skrip?

Sepertinya itu harus mudah, tapi itu sudah membuatku tersandung.


1573
2018-02-26 21:52


asal


Jawaban:


Menjawab

POSIX kompatibel:

command -v <the_command>

Untuk bash lingkungan khusus:

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

Penjelasan

Menghindari which. Tidak hanya itu proses eksternal yang Anda luncurkan untuk melakukan sangat sedikit (artinya builtins suka hash, type atau command jauh lebih murah), Anda juga dapat mengandalkan builtins untuk benar-benar melakukan apa yang Anda inginkan, sementara efek dari perintah eksternal dapat dengan mudah bervariasi dari sistem ke sistem.

Kenapa peduli?

  • Banyak sistem operasi memiliki which bahwa bahkan tidak menetapkan status keluar, artinya if which foo bahkan tidak akan bekerja di sana dan akan selalu laporkan itu foo ada, bahkan jika tidak (perhatikan bahwa beberapa kerang POSIX tampak melakukan ini untuk hash terlalu).
  • Banyak sistem operasi dibuat which lakukan hal-hal yang khusus dan jahat seperti mengubah output atau bahkan menghubungkannya dengan manajer paket.

Jadi, jangan gunakan which. Alih-alih gunakan salah satu dari ini:

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

(Catatan kecil: beberapa akan menyarankan 2>&- adalah sama 2>/dev/null tapi lebih pendek - ini tidak benar. 2>&- menutup FD 2 yang menyebabkan suatu kesalahan dalam program ketika mencoba untuk menulis ke stderr, yang sangat berbeda dari berhasil menulis ke sana dan membuang output (dan berbahaya!))

Jika hash bang Anda /bin/sh maka Anda harus peduli dengan apa yang dikatakan POSIX. type dan hashKode keluar tidak terlalu ditentukan dengan baik oleh POSIX, dan hash terlihat untuk keluar dengan sukses ketika perintah tidak ada (belum melihat ini dengan type namun). commandstatus keluar didefinisikan dengan baik oleh POSIX, sehingga salah satu mungkin yang paling aman untuk digunakan.

Jika skrip Anda menggunakan bash meskipun, aturan POSIX tidak terlalu penting lagi dan keduanya type dan hash menjadi sangat aman untuk digunakan. type sekarang memiliki -P untuk mencari hanya PATH dan hash memiliki efek samping bahwa lokasi perintah akan di-hash (untuk pencarian lebih cepat saat Anda menggunakannya), yang biasanya merupakan hal yang baik karena Anda mungkin memeriksa keberadaannya untuk benar-benar menggunakannya.

Sebagai contoh sederhana, inilah fungsi yang berjalan gdate jika ada, sebaliknya date:

gnudate() {
    if hash gdate 2>/dev/null; then
        gdate "$@"
    else
        date "$@"
    fi
}

2277
2018-03-24 12:45



Berikut ini adalah cara portabel untuk memeriksa apakah ada perintah $PATH  dan dapat dieksekusi:

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

Contoh:

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

Pemeriksaan yang dapat dieksekusi diperlukan karena bash mengembalikan file yang tidak dapat dieksekusi jika tidak ada file yang dapat dieksekusi dengan nama tersebut ditemukan $PATH.

Perhatikan juga bahwa jika file yang tidak dapat dieksekusi dengan nama yang sama dengan yang dapat dieksekusi sebelumnya ada $PATH, dash mengembalikan yang pertama, meskipun yang terakhir akan dieksekusi. Ini adalah bug dan melanggar standar POSIX. [Laporan bug] [Standar]

Selain itu, ini akan gagal jika perintah yang Anda cari telah didefinisikan sebagai alias.


236
2017-11-05 14:33



Saya setuju dengan lhunath untuk mencegah penggunaan which, dan solusinya sangat valid untuk pengguna BASH. Namun, agar lebih portabel, command -v akan digunakan sebagai gantinya:

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

Perintah command adalah POSIX compliant, lihat di sini untuk spesifikasinya: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/command.html

catatan: type adalah POSIX compliant, tapi type -P tidak.


190
2018-01-24 18:16



Saya memiliki fungsi yang didefinisikan dalam .bashrc saya yang membuatnya lebih mudah.

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

Berikut ini contoh penggunaannya (dari saya .bash_profile.)

if command_exists mvim ; then
    export VISUAL="mvim --nofork"
fi

81
2017-10-14 09:24



Itu tergantung apakah Anda ingin tahu apakah itu ada di salah satu direktori di $PATH variabel atau apakah Anda tahu lokasi absolutnya. Jika Anda ingin tahu apakah itu di $PATH variabel, gunakan

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

jika tidak, gunakan

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

Pengalihan ke /dev/null/ pada contoh pertama menekan output dari which program.


66
2018-02-26 22:01



Memperluas pada jawaban @ lhunath dan @ GregV, inilah kode untuk orang-orang yang ingin dengan mudah memasukkan cek itu ke dalam if pernyataan:

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

Beginilah cara menggunakannya:

if exists bash; then
  echo 'Bash exists!'
else
  echo 'Your system does not have Bash'
fi

27
2017-12-07 21:17



Coba gunakan:

test -x filename

atau

[ -x filename ]

Dari bash manpage di bawah Ekspresi Bersyarat:

 -x file
          True if file exists and is executable.

19
2018-02-26 21:57