Estou testando o shellcheck .
Eu tenho algo assim
basename "${OPENSSL}"
e recebo a seguinte sugestão
Use parameter expansion instead, such as ${var##*/}.
Do ponto de vista prático, não vejo diferença
$ export OPENSSL=/opt/local/bin/openssl
$ basename ${OPENSSL}
openssl
$ echo ${OPENSSL##*/}
openssl
Como basename
está nas especificações do POSIX , não faço uma razão para que seja uma prática recomendada. Alguma dica?
csh
. Eu acho quecsh
não é POSIX então.Respostas:
Não se trata de eficiência - é de correção.
basename
usa novas linhas para delimitar os nomes de arquivos impressos. No caso usual, quando você passa apenas um nome de arquivo, ele adiciona uma nova linha à sua saída. Como os nomes de arquivos podem conter novas linhas, isso dificulta o tratamento correto desses nomes de arquivo.É ainda mais complicada pelo fato de que as pessoas geralmente usam
basename
como este:"$(basename "$file")"
. Isso torna as coisas ainda mais difíceis, porque$(command)
retira todas as novas linhas finaiscommand
. Considere o caso improvável que$file
termina com uma nova linha. Em seguida,basename
irá adicionar uma nova linha extra, mas"$(basename "$file")"
irá retirar as duas novas linhas, deixando-o com um nome de arquivo incorreto.Outro problema
basename
é que, se$file
começar com um-
(traço aka menos), ele será interpretado como uma opção. Este é fácil de corrigir:$(basename -- "$file")
A maneira robusta de usar
basename
é esta:Uma alternativa é usar
${file##*/}
, o que é mais fácil, mas possui bugs próprios. Em particular, está errado nos casos em que$file
é/
oufoo/
.fonte
$file
forfoo/
? E se for/
?basename
abordagem é melhor, afinal, por mais hacky que seja. As melhores alternativas que posso encontrar são${${${file}%%/#}##*/}
e[[ $file =~ "([^/]*)/*$" ]] && printf "%s" $match[1]
, sendo ambas específicas do zsh e nenhuma das quais é manipulada/
corretamente.As linhas relevantes
shellcheck
do código fonte são:Não há explicação dada explicitamente, mas com base no nome da função (
checkNeedlessCommands
), parece que @jordanm está certo e sugere que você evite bifurcar um novo processo.fonte
dirname
,basename
,readlink
Etc (graças @Marco - este é corrigida) pode criar problemas de portabilidade quando a segurança torna-se importante (o que exige a segurança do caminho). Muitos sistemas (como o Fedora Linux) o colocam,/bin
enquanto outros (como o Mac OSX) o colocam/usr/bin
. Depois, há o Bash no Windows, por exemplo, cygwin, msys e outros.É sempre melhor manter o Bash puro, quando possível.(por comentário do @Marco)BTW, obrigado pelo ponteiro para verificar, eu nunca vi isso antes.
fonte
dirname
nada. 3) Os utilitários básicos básicos devem estar no PATH, onde quer que estejam armazenados. Ainda não vi um sistema quebasename
não estava no PATH. 4) Assumir que o bash está disponível é uma questão de portabilidade. É sempre melhor ficar longe do bash e usar um shell POSIX quando a portabilidade é necessária.posix
e nãobash
. Não consigo encontrar nenhum indicador de que o OP exija uma solução bash. Sua afirmação "É sempre melhor permanecer pura Bash" está completamente errada, me desculpe.