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.