J'essaie le shellcheck .
J'ai quelque chose comme ça
basename "${OPENSSL}"
et je reçois la suggestion suivante
Use parameter expansion instead, such as ${var##*/}.
D'un point de vue pratique, je ne vois aucune différence
$ export OPENSSL=/opt/local/bin/openssl
$ basename ${OPENSSL}
openssl
$ echo ${OPENSSL##*/}
openssl
Puisque basename
c'est dans les spécifications POSIX , je n'ai aucune raison pour que ce soit la meilleure pratique. Un indice?
csh
. Je suppose que cecsh
n'est pas POSIX alors.Réponses:
Ce n'est pas une question d'efficacité - c'est une question d'exactitude.
basename
utilise des retours à la ligne pour délimiter les noms de fichiers imprimés. Dans le cas habituel, lorsque vous ne passez qu'un seul nom de fichier, il ajoute une nouvelle ligne de fin à sa sortie. Étant donné que les noms de fichiers peuvent contenir eux-mêmes des sauts de ligne, il est difficile de gérer correctement ces noms de fichiers.Il est encore compliqué par le fait que les gens utilisent habituellement
basename
comme ceci:"$(basename "$file")"
. Cela rend les choses encore plus difficiles, car elles$(command)
suppriment toutes les nouvelles lignes de fincommand
. Considérez le cas peu probable qui$file
se termine par une nouvelle ligne. Ensuite ,basename
ajoutera une nouvelle ligne supplémentaire, mais"$(basename "$file")"
dépouillera les deux nouvelles lignes, vous laissant avec un nom de fichier incorrect.Un autre problème avec
basename
est que si$file
commence par un-
(tiret aka moins), il sera interprété comme une option. Celui-ci est facile à réparer:$(basename -- "$file")
La manière robuste d'utiliser
basename
est la suivante:Une alternative est d'utiliser
${file##*/}
, qui est plus facile mais qui a ses propres bugs. En particulier, c'est faux dans les cas où$file
est/
oufoo/
.la source
$file
estfoo/
? Et si c'est le cas/
?basename
approche est meilleure après tout, aussi hacky soit-elle. Les meilleures alternatives que je peux trouver sont${${${file}%%/#}##*/}
and[[ $file =~ "([^/]*)/*$" ]] && printf "%s" $match[1]
, qui sont toutes les deux spécifiques à zsh et qui ne gèrent pas/
correctement.Les lignes concernées
shellcheck
du » code source sont:Il n'y a aucune explication donnée explicitement mais basée sur le nom de la fonction (
checkNeedlessCommands
) il semble que @jordanm soit tout à fait raison et cela vous suggère d'éviter de bifurquer un nouveau processus.la source
dirname
,basename
,readlink
Etc (merci @Marco - ceci est corrigé) peut créer des problèmes de portabilité lorsque la sécurité est importante (nécessitant la sécurité du chemin). De nombreux systèmes (comme Fedora Linux) le placent sur/bin
tandis que d'autres (comme Mac OSX) le placent sur/usr/bin
. Ensuite, il y a Bash sur Windows, par exemple cygwin, msys et autres.Il est toujours préférable de rester pur Bash, lorsque cela est possible.(par commentaire @Marco)BTW, merci pour le pointeur sur shellcheck, je n'ai jamais vu ça avant.
la source
dirname
du tout. 3) Les utilitaires de base devraient être dans le CHEMIN, où qu'ils soient stockés. Je n'ai pas encore vu un système quibasename
n'était pas dans le CHEMIN. 4) En supposant que bash est disponible est un problème de portabilité. Il est toujours préférable de rester loin de bash et d'utiliser un shell POSIX lorsque la portabilité est requise.posix
et nonbash
. Je ne trouve aucun indicateur que l'OP nécessite une solution bash. Votre déclaration "Il vaut toujours mieux rester pur Bash" est tout simplement fausse, je suis désolé.