Estou programando um script de shell do Linux que imprimirá banners de status durante sua execução somente se a ferramenta apropriada, digamos figlet
, estiver instalada (isto é: alcançável no caminho do sistema ).
Exemplo:
#!/usr/bin/env bash
echo "foo"
figlet "Starting"
echo "moo"
figlet "Working"
echo "foo moo"
figlet "Finished"
Eu gostaria que meu script funcionasse sem erros mesmo quando não figlet
está instalado .
O que poderia ser um método prático ?
Minha interpretação usaria uma função wrapper com o mesmo nome da ferramenta; nessa função, execute a ferramenta real se ela existir:
Então você pode ter
figlet arg1 arg2...
inalterado em seu script.@Olorin surgiu com um método mais simples: defina uma função wrapper somente se precisarmos (se a ferramenta não existir):
Se você quiser que os argumentos
figlet
sejam impressos mesmo que o figlet não esteja instalado, ajuste a sugestão de Olorin da seguinte forma:Você pode testar para ver se
figlet
existeUma maneira comum de fazer isso é com
test -x
aka[ -x
. Aqui está um exemplo retirado de/etc/init.d/ntp
um sistema Linux:Essa variante depende de conhecer o caminho completo do executável. Em
/bin/lesspipe
encontrei um exemplo que contorna isso combinando-x
e owhich
comando:Dessa forma, isso funcionará sem saber com antecedência onde está
PATH
obunzip
executável.No início do seu script, verifique se
figlet
existe e, se não existir, defina uma função shell que não faça nada:type
verifica sefiglet
existe como shell embutido, função, alias ou palavra-chave,>/dev/null 2>&1
descarta stdin e stdout para que você não obtenha nenhuma saída e, se não existir,figlet() { :; }
definefiglet
como uma função que não faz nada.Dessa forma, você não precisa editar todas as linhas do seu script que usam
figlet
, ou verificar se ele existe toda vez quefiglet
é chamado.Você pode adicionar uma mensagem de diagnóstico, se desejar:
Como um bônus, já que você não mencionou qual shell está usando, acredito que seja compatível com POSIX, portanto, deve funcionar em praticamente qualquer shell.
Outra alternativa - um padrão que vi nos scripts de configuração automática do projeto:
No seu caso específico você poderia até fazer,
Se você não conhece o caminho específico, pode tentar vários
elif
(veja acima) para tentar locais conhecidos ou apenas usar oPATH
para sempre resolver o comando:Em geral, ao escrever scripts, prefiro chamar apenas comandos em locais específicos especificados por mim. Não gosto da incerteza/risco do que o usuário final pode ter colocado em seu
PATH
, talvez em seu próprio~/bin
.Se, por exemplo, eu estivesse escrevendo um script complicado para outros que possam remover arquivos com base na saída de um comando específico que estou chamando, não gostaria de pegar acidentalmente algo em seus
~/bin
que pode ou não ser o comando Eu esperava.O comando bash
type
encontra um comando, função, alias, palavra-chave ou built-in (consultehelp type
) e imprime a localização ou definição. Ele também retorna um código de retorno representando o resultado da pesquisa; verdadeiro (0) se encontrado. Então, o que estamos fazendo aqui é tentar encontrarfiglet
no caminho (-p
significa apenas procurar arquivos, não built-ins ou funções, e também suprime mensagens de erro), descartar a saída (é isso que> /dev/null
faz) e se retornar true (&&
) , ele será executadofiglet
.Isso é mais simples se
figlet
estiver em um local fixo:Aqui estamos usando o
test
comando (aka[
) para ver se/usr/bin/figlet
é executável (-x
) e se sim (&&
) execute-o. Esta solução eu acho que é mais portátil do que usartype
o que é um bashism que eu acredito.Você pode criar uma função que faça isso para você:
(As aspas são necessárias devido a possíveis espaços)
Então você só faria:
o/, eu diria algo como
Você pode fazer uma execução de teste, suprimindo qualquer saída e testar o código de sucesso/falha. Escolha argumentos para figlet para tornar este teste barato. -? ou --help ou --version são possibilidades óbvias.
Adicionado em resposta ao comentário abaixo: se você realmente deseja testar se o figlet existe, não que seja utilizável, você faria