Como posso verificar se um comando é um comando interno para ksh
?
Em tcsh
você pode usar where
; em zsh
e bash
você pode usar type -a
; e em algumas versões modernas de ksh
você pode usar whence -av
.
O que eu quero fazer é escrever uma função isbuiltin
que funcione em qualquer versão de ksh
(incluindo ksh88
e qualquer outra versão "antiga" de ksh
) que se comporte assim:
- Aceite vários argumentos e verifique se cada um deles está integrado
- Retornar
0
(sucesso) se todos os comandos fornecidos estiverem incorporados
- No primeiro comando não interno, interrompa a verificação, retorne
1
(falha) e imprima uma mensagem para stderr.
Já tenho funções de trabalho como esta para zsh
e bash
usando os comandos mencionados acima.
Aqui está o que eu tenho para 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
}
Esta função funciona para o ksh93. No entanto, parece que a versão do whence
do ksh88 não suporta a opção -a
, que é a opção para mostrar todas as ocorrências. Sem a capacidade de exibir todas as ocorrências, só posso usar whence -v
, o que faz dizer se um comando é interno, mas somente se não houver também um alias ou função de mesmo nome .
Pergunta: há mais alguma coisa que eu possa usar no lugar de whence -av
em ksh88
?
Solução
Usando a resposta aceita (abrindo um subshell), aqui está minha solução atualizada. Coloque o seguinte em .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
}
Eu testei isso com o ksh88 no Solaris, AIX e HP-UX. Ele funciona em todos os casos que testei. Eu também testei isso com as versões modernas do ksh no FreeBSD, Ubuntu, Fedora e Debian.