Làm cách nào để kiểm tra xem ứng dụng có tồn tại trong $ PATH không?


19

Tôi đang cố gắng viết tất cả các shtập lệnh khởi động / env của mình để hoạt động với càng nhiều DRY và càng nhiều: "hoạt động trên mọi * nix tôi sao chép nó", càng tốt. Điều này có nghĩa là đảm bảo rằng nếu tôi cố chạy mã không có ở đó, thì mã đó sẽ thất bại. Để đạt được điều đó, tôi cần có thể kiểm tra nếu các chương trình tồn tại. Tôi biết cách kiểm tra nếu một tệp tồn tại, nhưng tôi không chắc chắn cách kiểm tra để xem ứng dụng có thể thực thi được trong đường dẫn hay không. Tôi thà sử dụng $ PATH, vì một số trong số này cần phải hoạt động trên arch, ubfox và centos. Một số có thể được cài đặt trong homedir của tôi, trên các hệ thống mà tôi không có root, một số khác có thể không được cài đặt và những cái khác chưa được cài đặt trong đường dẫn hệ thống.


2
Đây câu trả lời SO là một trong tôi đã đánh dấu cho các câu hỏi như vậy.
jw013

Câu trả lời:


19

Sử dụng type commandname. Điều này trả về true nếu commandnamecó bất cứ thứ gì có thể thực thi được: bí danh, hàm, lệnh tích hợp hoặc lệnh bên ngoài (tra cứu $PATH). Ngoài ra, sử dụng command commandnametrả về true nếu commandnamelà lệnh tích hợp hoặc bên ngoài (tra cứu $PATH).

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

Có một vài biến thể sh (chắc chắn là tiền POSIX; tôi biết trong /bin/shOSF1 3.x và một số phiên bản của vỏ Almquist được tìm thấy trong các phiên bản NetBSD đầu tiên và một vài bản phân phối Linux thế kỷ 20) typeluôn trả về 0 hoặc không hiện hữu. Tôi không nghĩ rằng bất kỳ hệ thống nào được vận chuyển trong thiên niên kỷ này. Nếu bạn từng gặp chúng, đây là một chức năng bạn có thể sử dụng để tìm kiếm $PATHtheo cách thủ công:

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

Hàm này thường hữu ích nếu bạn muốn loại trừ các hàm dựng sẵn và các hàm và tìm kiếm tên trong đó $PATH. Hầu hết các shell đều được tích hợp sẵn cho điều này, command -vmặc dù đây là một bổ sung tương đối gần đây cho POSIX (vẫn là tùy chọn kể từ POSIX: 2004). Về cơ bản, đây là phiên bản thân thiện với lập trình viên type: nó in đường dẫn đầy đủ cho một tệp thực thi $PATH, tên trần cho hàm tích hợp hoặc hàm và định nghĩa bí danh cho bí danh.

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

Ksh, bash và zsh cũng phải type -ptìm kiếm chỉ thực thi trong $PATH. Lưu ý rằng trong bash, trạng thái trả về type -p foolà 0 nếu foolà hàm tích hợp hoặc hàm; nếu bạn muốn kiểm tra một tệp thực thi $PATH, bạn cần kiểm tra xem đầu ra không trống. type -pkhông có trong POSIX; ví dụ tro của Debian ( /bin/shtrên Ubuntu) không có nó.


@gilles, điều này (hoặc một cái gì đó tương tự) sẽ if [ type keychain ]; thenkhông hoạt động? Tôi gặp lỗi /home/xenoterracide/.zshrc:84: parse error: condition expected: typeTôi cho rằng tôi có thể viết hàm tồn tại ... Tôi chỉ nghĩ rằng điều này có thể đơn giản hơn theo nghĩa ...
xenoterracide

@xenoterracide: Thả dấu ngoặc!
Gilles 'SO- ngừng trở nên xấu xa'

Tôi nghĩ rằng bạn đang tìm kiếm if type $APP >/dev/null 2>/dev/null; then ...Bạn không muốn [].
Steven D

4
Bah, tôi biết tôi nên đã làm mới. Bị đánh bại bởi Gilles một lần nữa!
Steven D

type -pnếu bạn đặc biệt tìm kiếm một lệnh trong $PATH(không phải bí danh hoặc hàm hoặc nội trang).
ephemient

1

Nếu bạn chỉ tìm kiếm các chương trình bên ngoài, bạn cũng có thể sử dụng chương trình nào. Không biết làm thế nào di động được mặc dù.


3
Về lý thuyết, nó ít di động hơn typehoặc command; whichkhông có trong POSIX, ví dụ. Trong thực tế, whichtồn tại hầu hết mọi nơi, nhưng ở một số nơi (nơi nó được triển khai như một tập lệnh csh), nó sử dụng một đường dẫn khác (do a .cshrc), đánh bại mục đích.
Gilles 'SO- ngừng trở nên xấu xa'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.