Scripting
檢查命令是否是 ksh 中的內置命令
如何檢查命令是否是內置命令
ksh
?在
tcsh
你可以使用where
; 在中zsh
,bash
您可以使用type -a
;在某些現代版本中,ksh
您可以使用whence -av
.我想做的是編寫一個
isbuiltin
可以在任何版本ksh
(包括ksh88
和任何其他“舊”版本ksh
)中執行的函式,其行為如下:
- 接受多個參數並檢查每個參數是否是內置的
0
如果所有給定的命令都是內置的,則返回(成功)- 在第一個非內置命令處,停止檢查,返回
1
(失敗),並將消息列印到 stderr。我已經為
zsh
和bash
使用上述命令提供了這樣的工作功能。這是我所擁有的
ksh
:isbuiltin() { if [[ "$#" -eq 0 ]]; then echo "Usage: isbuiltin cmd" >&2 return 1 fi for cmd in "$@" do if [[ $cmd = "builtin" ]]; then #Handle the case of `builtin builtin` echo "$cmd is not a built-in" >&2 return 1 fi if ! whence -a "$cmd" 2> /dev/null | grep 'builtin' > /dev/null ; then echo "$cmd is not a built-in" >&2 return 1 fi done }
此功能適用於 ksh93。但是,似乎 ksh88 的版本
whence
不支持該-a
選項,該選項是使其顯示所有出現的選項。由於無法顯示所有事件,我只能使用whence -v
,它確實告訴我命令是否是內置的,但前提是沒有同名的別名或函式。**問題:**我可以用其他東西代替
whence -av
inksh88
嗎?解決方案
使用接受的答案(打開子shell),這是我更新的解決方案。將以下內容放在 .kshrc 中:
isbuiltin() { if [[ "$#" -eq 0 ]]; then printf "Usage: isbuiltin cmd\n" >&2 return 1 fi for cmd in "$@" do if ( #Open a subshell so that aliases and functions can be safely removed, # allowing `whence -v` to see the built-in command if there is one. unalias "$cmd"; if [[ "$cmd" != '.' ]] && typeset -f | egrep "^(function *$cmd|$cmd\(\))" > /dev/null 2>&1 then #Remove the function iff it exists. #Since `unset` is a special built-in, the subshell dies if it fails unset -f "$cmd"; fi PATH='/no'; #NOTE: we can't use `whence -a` because it's not supported in older versions of ksh whence -v "$cmd" 2>&1 ) 2> /dev/null | grep -v 'not found' | grep 'builtin' > /dev/null 2>&1 then #No-op. Needed to support some old versions of ksh : else printf "$cmd is not a built-in\n" >&2 return 1 fi done return 0 }
我已經在 Solaris、AIX 和 HP-UX 中使用 ksh88 對此進行了測試。它適用於我測試的所有情況。我還在 FreeBSD、Ubuntu、Fedora 和 Debian 中使用現代版本的 ksh 對此進行了測試。
如果您擔心別名,只需執行以下操作:
[[ $(unalias -- "$cmd"; type -- "$cmd") = *builtin ]]
(
$(...)
創建一個子shell環境,所以unalias
只在那裡有效)。如果你也關心函式,也可以執行
command unset -f -- "$cmd"
beforetype
。
我擔心您可能會浪費時間來實現它;
ksh93
支持builtin
命令。例如ksh version 93t 2008-11-04
:$ builtin ...creates list of all builtins $ builtin jobs umask ...returns with exit code 0 $ builtin jobs time umask ...returns with exit code 1 and prints "builtin: time: not found"
另請注意,該
builtin
命令是內置命令,因此您在程式碼中排除此特定內置命令的測試似乎不正確。