Làm thế nào để tôi xác nhận rằng một chương trình tồn tại, theo cách sẽ trả lại lỗi và thoát, hoặc tiếp tục với tập lệnh?
Có vẻ như nó dễ dàng, nhưng nó đã làm tôi thất vọng.
Làm thế nào để tôi xác nhận rằng một chương trình tồn tại, theo cách sẽ trả lại lỗi và thoát, hoặc tiếp tục với tập lệnh?
Có vẻ như nó dễ dàng, nhưng nó đã làm tôi thất vọng.
Câu trả lời:
Tương thích POSIX:
command -v <the_command>
Đối với môi trường cụ thể của Bash:
hash <the_command> # For regular commands. Or...
type <the_command> # To check built-ins and keywords
Tránh which
. Đây không chỉ là một quá trình bên ngoài mà bạn khởi chạy để thực hiện rất ít (có nghĩa là các nội dung như hash
, type
hoặc command
rẻ hơn), bạn cũng có thể dựa vào các nội dung để thực sự làm những gì bạn muốn, trong khi hiệu ứng của các lệnh bên ngoài có thể dễ dàng thay đổi từ hệ thống đến hệ thống.
Tại sao phải quan tâm?
which
mà thậm chí không thiết lập một trạng thái thoát , có nghĩa là if which foo
thậm chí sẽ không làm việc ở đó và sẽ luôn luôn báo cáo rằng foo
tồn tại, ngay cả khi nó không (lưu ý rằng một số vỏ POSIX xuất hiện để làm việc này cho hash
quá).which
hiện các công cụ tùy chỉnh và xấu xa như thay đổi đầu ra hoặc thậm chí móc vào trình quản lý gói.Vì vậy, không sử dụng which
. Thay vào đó hãy sử dụng một trong những cách sau:
$ 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; }
(Tiểu phụ lưu ý: một số sẽ đề nghị 2>&-
là như nhau 2>/dev/null
nhưng ngắn hơn - đây là không đúng sự thật . 2>&-
Đóng vai trò quant FD 2 gây ra một lỗi trong chương trình khi nó cố gắng để viết thư cho stderr, mà là rất khác nhau từ văn bản thành công với nó và vứt bỏ đầu ra (và nguy hiểm!))
Nếu băm của bạn là /bin/sh
thì bạn nên quan tâm đến những gì POSIX nói. type
và hash
mã thoát không được xác định rõ bằng POSIX và hash
được xem là thoát thành công khi lệnh không tồn tại (chưa thấy điều này type
). command
Trạng thái thoát của POSIX được xác định rõ, do đó có thể là trạng thái an toàn nhất để sử dụng.
Nếu tập lệnh của bạn sử dụng bash
mặc dù, các quy tắc POSIX không thực sự quan trọng nữa và cả hai type
và hash
trở nên hoàn toàn an toàn để sử dụng. type
bây giờ -P
chỉ cần tìm kiếm PATH
và hash
có tác dụng phụ là vị trí của lệnh sẽ được băm (để tra cứu nhanh hơn vào lần tới khi bạn sử dụng nó), đây thường là một điều tốt vì bạn có thể kiểm tra sự tồn tại của nó để thực sự sử dụng nó .
Ví dụ đơn giản, đây là một hàm chạy gdate
nếu nó tồn tại, nếu không date
:
gnudate() {
if hash gdate 2>/dev/null; then
gdate "$@"
else
date "$@"
fi
}
2>&-
("mô tả tệp đầu ra đóng 2", đó là stderr) có kết quả tương tự như 2> /dev/null
; 2) >&2
là một lối tắt cho 1>&2
, mà bạn có thể nhận ra là "chuyển hướng stdout sang stderr". Xem trang Chuyển hướng Bash Bashing nâng cao để biết thêm thông tin.
while read element ; do .. done <<< $(echo ${ArrayVar[*]})
, for word in $(fgrep -l $ORIGINAL *.txt)
, ls -l "$directory" | sed 1d
, {{cho một trong seq $BEGIN $END
}}, ... Nhiều người đã cố gắng liên hệ với tác giả và đề xuất cải tiến nhưng nó không wiki và yêu cầu đã hạ cánh vào tai điếc.
2>&-
là không giống như 2>/dev/null
. Cái trước đóng bộ mô tả tập tin, trong khi cái sau chỉ đơn giản là chuyển hướng nó đến /dev/null
. Bạn có thể không thấy lỗi vì chương trình cố gắng thông báo cho bạn trên stderr rằng stderr đã bị đóng.
Sau đây là một cách di động để kiểm tra xem một lệnh có tồn tại $PATH
hay không và có thể thực thi được không:
[ -x "$(command -v foo)" ]
Thí dụ:
if ! [ -x "$(command -v git)" ]; then
echo 'Error: git is not installed.' >&2
exit 1
fi
Kiểm tra thực thi là cần thiết bởi vì bash trả về một tệp không thể thực thi nếu không tìm thấy tệp thực thi có tên đó $PATH
.
Cũng lưu ý rằng nếu một tệp không thể thực thi có cùng tên với tệp thực thi tồn tại trước đó $PATH
, dấu gạch ngang trả về tệp trước , mặc dù tệp sau sẽ được thực thi. Đây là một lỗi và vi phạm tiêu chuẩn POSIX. [ Báo cáo lỗi ] [ Tiêu chuẩn ]
Ngoài ra, điều này sẽ thất bại nếu lệnh bạn đang tìm kiếm được xác định là bí danh.
command -v
tạo ra một đường dẫn ngay cả đối với một tệp không thể thực thi? Đó là, -x thực sự cần thiết?
-x
kiểm tra xem tập tin có thể thực thi được không, đó là câu hỏi gì.
command
chính nó sẽ kiểm tra khả năng thực thi của nó - phải không?
$PATH
khi thực hiện lệnh. Tuy nhiên, hành vi của command -v
rất không nhất quán. Trong dấu gạch ngang, nó trả về tệp phù hợp đầu tiên trong $PATH
, bất kể nó có thực thi được hay không. Trong bash, nó trả về kết quả khớp thực thi đầu tiên trong $PATH
, nhưng nếu không có, nó có thể trả về một tệp không thể thực thi. Và trong zsh, nó sẽ không bao giờ trả lại một tệp không thể thực thi.
dash
là người duy nhất trong số ba người không tuân thủ POSIX; [ -x "$(command -v COMMANDNAME)"]
sẽ làm việc trong hai người kia. Trông giống như lỗi này đã được báo cáo nhưng chưa có bất kỳ phản hồi nào: bugs.debian.org/cgi-bin/bugreport.cgi?bug=874264
Tôi đồng ý với lhunath để không khuyến khích sử dụng which
và giải pháp của anh ấy hoàn toàn hợp lệ đối với người dùng Bash . Tuy nhiên, để dễ di chuyển hơn, command -v
sẽ được sử dụng thay thế:
$ command -v foo >/dev/null 2>&1 || { echo "I require foo but it's not installed. Aborting." >&2; exit 1; }
Lệnh command
tuân thủ POSIX. Xem ở đây để biết đặc điểm kỹ thuật của nó: lệnh - thực hiện một lệnh đơn giản
Lưu ý: type
là tuân thủ POSIX, nhưng type -P
không.
exit 1;
giết một xterm, nếu được gọi từ đó.
&>/dev/null
. Tuy nhiên, tôi đồng ý với bạn, điều thực sự quan trọng là tính di động, tôi đã chỉnh sửa câu trả lời của mình cho phù hợp, hiện đang sử dụng chuyển hướng sh tiêu chuẩn >/dev/null 2>&1
.
Tôi có một hàm được định nghĩa trong .bashrc giúp việc này dễ dàng hơn.
command_exists () {
type "$1" &> /dev/null ;
}
Đây là một ví dụ về cách nó được sử dụng (từ của tôi .bash_profile
.)
if command_exists mvim ; then
export VISUAL="mvim --nofork"
fi
&>
?
&>
chuyển hướng cả stdout và stderr với nhau.
&>
có thể không có sẵn trong phiên bản Bash của bạn. Mã của Marcello sẽ hoạt động tốt; Nó làm điều tương tự.
then
Ví dụ : Hãy thử điều này với từ này . Xem câu trả lời này nếu bạn yêu cầu thực thi tồn tại $PATH
.
Nó phụ thuộc vào việc bạn muốn biết liệu nó có tồn tại trong một trong các thư mục trong $PATH
biến hay bạn có biết vị trí tuyệt đối của nó hay không. Nếu bạn muốn biết nó có trong $PATH
biến không, hãy sử dụng
if which programname >/dev/null; then
echo exists
else
echo does not exist
fi
nếu không thì sử dụng
if [ -x /path/to/programname ]; then
echo exists
else
echo does not exist
fi
Việc chuyển hướng đến /dev/null/
trong ví dụ đầu tiên triệt tiêu đầu ra của which
chương trình.
Mở rộng câu trả lời của @ lhunath và @ GregV, đây là mã dành cho những người muốn dễ dàng đưa kiểm tra đó vào trong một if
tuyên bố:
exists()
{
command -v "$1" >/dev/null 2>&1
}
Đây là cách sử dụng nó:
if exists bash; then
echo 'Bash exists!'
else
echo 'Your system does not have Bash'
fi
command
thành công ngay cả đối với các bí danh, có thể hơi phản trực giác. Kiểm tra sự tồn tại trong một vỏ tương tác sẽ cho kết quả khác nhau từ khi bạn chuyển nó sang một tập lệnh.
shopt -u expand_aliases
bỏ qua / ẩn các bí danh (như alias ls='ls -F'
được đề cập trong câu trả lời khác) và shopt -s expand_aliases
giải quyết chúng thông qua command -v
. Vì vậy, có lẽ nó nên được đặt trước kiểm tra và bỏ đặt sau, mặc dù nó có thể ảnh hưởng đến giá trị trả về của hàm nếu bạn không nắm bắt và trả lại đầu ra của lệnh gọi một cách rõ ràng.
Hãy thử sử dụng:
test -x filename
hoặc là
[ -x filename ]
Từ trang quản lý Bash dưới Biểu thức có điều kiện :
-x file True if file exists and is executable.
Để sử dụng hash
, như @lhunath gợi ý , trong tập lệnh Bash:
hash foo &> /dev/null
if [ $? -eq 1 ]; then
echo >&2 "foo not found."
fi
Kịch bản lệnh này chạy hash
và sau đó kiểm tra xem mã thoát của lệnh gần đây nhất, giá trị được lưu trữ trong $?
, có bằng không 1
. Nếu hash
không tìm thấy foo
, mã thoát sẽ là 1
. Nếu foo
có, mã thoát sẽ là 0
.
&> /dev/null
chuyển hướng lỗi tiêu chuẩn và đầu ra tiêu chuẩn từ hash
đó để nó không xuất hiện trên màn hình và echo >&2
ghi thông báo thành lỗi tiêu chuẩn.
if hash foo &> /dev/null; then ...
?
Tôi chưa bao giờ có được câu trả lời trước để làm việc trên hộp tôi có quyền truy cập. Đối với một, type
đã được cài đặt (làm những gì more
làm). Vì vậy, chỉ thị dựng sẵn là cần thiết. Lệnh này hoạt động với tôi:
if [ `builtin type -p vim` ]; then echo "TRUE"; else echo "FALSE"; fi
if
cú pháp, chỉ cần sử dụng if builtin type -p vim; then ...
. Và backticks là cú pháp thực sự cổ xưa và không dùng nữa, $()
được hỗ trợ ngay cả sh
trên tất cả các hệ thống hiện đại.
Kiểm tra nhiều phụ thuộc và thông báo trạng thái cho người dùng cuối
for cmd in latex pandoc; do
printf '%-10s' "$cmd"
if hash "$cmd" 2>/dev/null; then
echo OK
else
echo missing
fi
done
Đầu ra mẫu:
latex OK
pandoc missing
Điều chỉnh 10
độ dài lệnh tối đa. Nó không tự động, vì tôi không thấy cách POSIX không dài dòng để làm điều đó:
Làm cách nào tôi có thể căn chỉnh các cột của một bảng được phân tách không gian trong Bash?
Kiểm tra nếu một số apt
gói được cài đặt dpkg -s
và cài đặt chúng khác .
Xem: Kiểm tra xem gói apt-get đã được cài đặt chưa và sau đó cài đặt gói đó nếu không có trên Linux
Nó đã được đề cập trước đây tại: Làm cách nào tôi có thể kiểm tra xem chương trình có tồn tại từ tập lệnh Bash không?
column -t
(một phần của linux-linux).
Nếu bạn kiểm tra sự tồn tại của chương trình, có lẽ bạn sẽ chạy nó sau. Tại sao không thử chạy nó ở nơi đầu tiên?
if foo --version >/dev/null 2>&1; then
echo Found
else
echo Not found
fi
Đó là một kiểm tra đáng tin cậy hơn rằng chương trình chạy hơn là chỉ xem các thư mục PATH và quyền truy cập tệp.
Ngoài ra, bạn có thể nhận được một số kết quả hữu ích từ chương trình của mình, chẳng hạn như phiên bản của nó.
Tất nhiên nhược điểm là một số chương trình có thể nặng để bắt đầu và một số không có --version
tùy chọn để thoát ngay lập tức (và thành công).
hash foo 2>/dev/null
: hoạt động với vỏ Z (Zsh), Bash, Dash và tro .
type -p foo
: nó dường như hoạt động với Z shell, Bash và ash ( BusyBox ), nhưng không phải Dash (nó diễn giải -p
như một đối số).
command -v foo
: hoạt động với Z shell, Bash, Dash, nhưng không tro (BusyBox) ( -ash: command: not found
).
Cũng lưu ý rằng builtin
không có sẵn với tro và Dash.
Sử dụng nội dung Bash nếu bạn có thể:
which programname
...
type -P programname
which
không phải là một nội dung Bash.
-P
là không phải POSIX. Tại sao được type -P
ưa thích?
Lệnh -v
hoạt động tốt nếu tùy chọn POSIX_BUILTINS được đặt cho<command>
để kiểm tra, nhưng nó có thể thất bại nếu không. (Nó đã làm việc cho tôi trong nhiều năm, nhưng gần đây tôi đã chạy vào một nơi mà nó không hoạt động.)
Tôi thấy những điều sau đây là không thể hơn:
test -x $(which <command>)
Vì nó kiểm tra ba thứ: đường dẫn, sự tồn tại và sự cho phép thực thi.
test -x $(which ls)
trả về 0, như vậy test -x $(which sudo)
, mặc dù đã ls
được cài đặt và có thể chạy được và sudo
thậm chí không được cài đặt trong bộ chứa docker mà tôi đang chạy.
test -x "$(which <command>)"
ls
là bí danh? Tôi không nghĩ rằng nó sẽ hoạt động nếu lệnh có tham số.
Đối với những người quan tâm, không có phương pháp nào trong các câu trả lời trước hoạt động nếu bạn muốn phát hiện một thư viện đã cài đặt. Tôi tưởng tượng bạn còn lại với việc kiểm tra thực tế đường dẫn (có khả năng cho các tệp tiêu đề và tương tự) hoặc đại loại như thế này (nếu bạn đang ở trên bản phân phối dựa trên Debian):
dpkg --status libdb-dev | grep -q not-installed
if [ $? -eq 0 ]; then
apt-get install libdb-dev
fi
Như bạn có thể thấy ở trên, câu trả lời "0" từ truy vấn có nghĩa là gói không được cài đặt. Đây là chức năng của "grep" - "0" có nghĩa là trận đấu được tìm thấy, "1" có nghĩa là không tìm thấy kết quả khớp nào.
cmd; if [ $? -eq 0 ]; then
nên được tái cấu trúc thànhif cmd; then
dpkg
hoặcapt
Có rất nhiều lựa chọn ở đây, nhưng tôi đã ngạc nhiên khi không có một lớp lót nhanh nào. Đây là những gì tôi đã sử dụng ở đầu tập lệnh của mình:
[[ "$(command -v mvn)" ]] || { echo "mvn is not installed" 1>&2 ; exit 1; }
[[ "$(command -v java)" ]] || { echo "java is not installed" 1>&2 ; exit 1; }
Điều này dựa trên câu trả lời được chọn ở đây và một nguồn khác.
Tôi muốn nói rằng không có cách nào di động và đáng tin cậy 100% do lơ lửng alias
es. Ví dụ:
alias john='ls --color'
alias paul='george -F'
alias george='ls -h'
alias ringo=/
Tất nhiên, chỉ có điều cuối cùng là có vấn đề (không có ý xúc phạm đến Ringo!). Nhưng tất cả chúng đều là alias
es hợp lệ theo quan điểm của command -v
.
Để từ chối những cái lủng lẳng như thế ringo
, chúng ta phải phân tích đầu ra của lệnh tích hợp shell alias
và tái sử dụng chúng ( command -v
không phải là ưu việt alias
ở đây.) Không có bất kỳ giải pháp di động nào cho nó, và thậm chí là Bash- giải pháp cụ thể là khá tẻ nhạt.
Lưu ý rằng một giải pháp như thế này sẽ từ chối vô điều kiện alias ls='ls -F'
:
test() { command -v $1 | grep -qv alias }
shopt -u expand_aliases
bỏ qua / ẩn các bí danh này và shopt -s expand_aliases
hiển thị chúng qua command -v
.
Điều này sẽ cho biết theo vị trí nếu chương trình tồn tại hay không:
if [ -x /usr/bin/yum ]; then
echo "This is Centos"
fi
Các which
lệnh có thể có ích. người đàn ông mà
Nó trả về 0 nếu thực thi được tìm thấy và trả về 1 nếu không tìm thấy hoặc không thực thi:
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 executable
2 if an invalid option is specified
Điều thú vị which
là nó chỉ ra nếu thực thi có sẵn trong môi trường which
được chạy trong - nó sẽ lưu một vài vấn đề ...
Thiết lập của tôi cho Debian máy chủ :
Tôi gặp vấn đề khi nhiều gói chứa cùng một tên.
Ví dụ apache2
. Vì vậy, đây là giải pháp của tôi:
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
}
Nếu các bạn / cô gái không thể có được những điều trong câu trả lời ở đây để làm việc và đang nhổ tóc ra khỏi lưng, hãy thử chạy cùng một lệnh bằng cách sử dụng bash -c
. Chỉ cần nhìn vào mê sảng somnambular này. Đây là những gì thực sự xảy ra khi bạn chạy $ (lệnh phụ):
Đầu tiên. Nó có thể cung cấp cho bạn đầu ra hoàn toàn khác nhau.
$ command -v ls
alias ls='ls --color=auto'
$ bash -c "command -v ls"
/bin/ls
Thứ hai. Nó có thể cung cấp cho bạn không có đầu ra nào cả.
$ command -v nvm
nvm
$ bash -c "command -v nvm"
$ bash -c "nvm --help"
bash: nvm: command not found
.bashrc
có một khoản dự phòng [ -z "$PS1" ] && return
trước # If not running interactively, don't do anything
vì vậy tôi đoán đó là lý do tại sao ngay cả việc tìm nguồn cung ứng bashrc rõ ràng trong chế độ không tương tác cũng không giúp ích được gì. Vấn đề có thể được giải quyết bằng cách gọi một tập lệnh với toán tử dấu chấm ss64.com/bash/source.html. ./script.sh
nhưng đó không phải là điều người ta muốn nhớ để nhập mỗi lần.
Biến thể băm có một cạm bẫy: Trên dòng lệnh, ví dụ bạn có thể nhập vào
one_folder/process
để có quá trình thực hiện. Đối với điều này, thư mục mẹ của one_folder phải ở trong $ PATH . Nhưng khi bạn cố gắng băm lệnh này, nó sẽ luôn thành công:
hash one_folder/process; echo $? # will always output '0'
$PATH
" Đây là hoàn toàn không chính xác. Thử nó. Để làm việc này, one_folder phải nằm trong thư mục hiện tại .
Tôi thứ hai sử dụng "lệnh -v". Ví dụ như thế này:
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
Tôi đã phải kiểm tra xem Git đã được cài đặt như là một phần của việc triển khai máy chủ CI của chúng tôi chưa . Kịch bản Bash cuối cùng của tôi là như sau (máy chủ Ubuntu):
if ! builtin type -p git &>/dev/null; then
sudo apt-get -y install git-core
fi
sudo
: không có điều kiện, nó sẽ luôn dừng lại và yêu cầu mật khẩu (trừ khi bạn đã làm một sudo gần đây). BTW, nó có thể hữu ích để làm sudo -p "Type your password to install missing git-core: "
như vậy nhắc nhở không đi ra khỏi màu xanh.
Để bắt chước Bash type -P cmd
, chúng ta có thể sử dụng tuân thủ POSIX env -i type cmd 1>/dev/null 2>&1
.
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>&1 || { echo "$cmd not found"; exit 1; }
type
dường như là một builtin
phần lớn các shell nên điều này không thể hoạt động được vì env
sử dụng execvp
để chạy command
nên command
không thể là một builtin
(và builtin
sẽ luôn được chạy trong cùng một môi trường). Đây không cho tôi ở bash
, ksh93
, zsh
, busybox [a]sh
và dash
tất cả trong số đó cung cấp type
như một BUILTIN vỏ.
Nếu không có bất kỳ type
lệnh bên ngoài nào khả dụng (như được cấp ở đây ), chúng ta có thể sử dụng tuân thủ POSIX env -i sh -c 'type cmd 1>/dev/null 2>&1'
:
# Portable version of Bash's type -P cmd (without output on stdout)
typep() {
command -p env -i PATH="$PATH" sh -c '
export LC_ALL=C LANG=C
cmd="$1"
cmd="`type "$cmd" 2>/dev/null || { echo "error: command $cmd not found; exiting ..." 1>&2; exit 1; }`"
[ $? != 0 ] && exit 1
case "$cmd" in
*\ /*) exit 0;;
*) printf "%s\n" "error: $cmd" 1>&2; exit 1;;
esac
' _ "$1" || exit 1
}
# Get your standard $PATH value
#PATH="$(command -p getconf PATH)"
typep ls
typep builtin
typep ls-temp
Ít nhất trên Mac OS X v10.6.8 (Snow Leopard) sử dụng Bash 4.2.24 (2) command -v ls
không khớp với di chuyển /bin/ls-temp
.
Trong trường hợp bạn muốn kiểm tra xem một chương trình có tồn tại và thực sự là một chương trình, không phải là lệnh tích hợp Bash , sau đó command
, type
vàhash
không thích hợp để thử nghiệm như tất cả họ đều trở về 0 trạng thái thoát cho built-in lệnh.
Ví dụ, có chương trình thời gian cung cấp nhiều tính năng hơn lệnh tích hợp thời gian . Để kiểm tra xem chương trình có tồn tại không, tôi sẽ đề nghị sử dụng which
như trong ví dụ sau:
# 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
Tôi muốn câu hỏi tương tự được trả lời nhưng để chạy trong Makefile.
install:
@if [[ ! -x "$(shell command -v ghead)" ]]; then \
echo 'ghead does not exist. Please install it.'; \
exit -1; \
fi
Kịch bản
#!/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"'
Kết quả
✘ [ABRT]: notacmd: command does not exist
hits command
0 /usr/bin/bash
Fin.
Tôi sử dụng cái này, vì nó rất dễ:
if [ `LANG=C type example 2>/dev/null|wc -l` = 1 ];then echo exists;else echo "not exists";fi
hoặc là
if [ `LANG=C type example 2>/dev/null|wc -l` = 1 ];then
echo exists
else echo "not exists"
fi
Nó sử dụng trạng thái echo của shell và chương trình cho đầu ra tiêu chuẩn và không có gì xảy ra lỗi tiêu chuẩn. Mặt khác, nếu không tìm thấy lệnh, nó chỉ báo trạng thái lỗi cho lỗi tiêu chuẩn.
which
trả về đúng cho những điều này.type
không có đối số cũng sẽ trả về true cho các từ dành riêng và nội dung shell. Nếu "chương trình" có nghĩa là "có thể giải thích được$PATH
", thì hãy xem câu trả lời này .