Notez que coreutils
est un ensemble de logiciels développé par le projet GNU pour fournir un ensemble d'utilitaires de base Unix aux systèmes GNU. Vous ne trouverez que coreutils echo
prêt à l'emploi sur les systèmes GNU (Debian
, trisquel
, Cygwin
, Fedora
, CentOS
...). Sur d'autres systèmes, vous trouverez un autre (généralement avec un comportement différent comme echo
est l'une des applications les moins portables). FreeBSD aura FreeBSD echo
, la plupart des systèmes basés sur Linux auront busybox echo
, AIX aura AIX echo
...
Certains systèmes en auront même plus d'un (comme /bin/echo
et /usr/ucb/echo
sur Solaris (ce dernier faisant partie d'un package désormais facultatif dans les versions ultérieures de Solaris, comme le package d'utilitaires for GNU à partir duquel vous obtiendriez un /usr/gnu/bin/echo
) tous avec des CLI différentes).
GNU coreutils
a été porté sur la plupart des systèmes de type Unix (et même non-Unix comme MS Windows), vous pourrez donc compiler coreutils
' echo
sur la plupart des systèmes, mais ce n'est probablement pas ce que vous recherchez.
Notez également que vous trouverez des incompatibilités entre les versions de coreutils
echo
(par exemple, il ne reconnaissait pas \x41
séquences avec -e
) et que son comportement peut être affecté par l'environnement (POSIXLY_CORRECT
variable).
Maintenant, pour exécuter le echo
du système de fichiers (trouvé par une recherche de $PATH
), comme pour toutes les autres commandes intégrées, la manière typique est avec env
:
env echo this is not the builtin echo
En zsh
(lorsqu'il n'émule pas d'autres shells), vous pouvez également faire :
command echo ...
sans avoir à exécuter un env
supplémentaire commande.
Mais j'espère que le texte ci-dessus indique clairement que cela ne va pas aider en ce qui concerne la portabilité. Pour la portabilité et la fiabilité, utilisez printf
à la place.
# $(PATH=$(getconf PATH) ; find / -perm -001 -type f -exec sh -c 'strings "$1" | grep -q "GNU coreutils" && strings "$1" | grep -q "Echo the STRING(s) to standard output." && printf "%s" "$1"' sh {} \; | head -n 1) --help
Usage: /bin/echo [SHORT-OPTION]... [STRING]...
or: /bin/echo LONG-OPTION
...
or available locally via: info '(coreutils) echo invocation'
Je pense que c'est une mauvaise idée, pour être honnête, mais cela fera un travail assez solide pour trouver les coreutils echo
dans un environnement raisonnable. Ce sont des commandes compatibles POSIX tout du long (getconf
, find
, sh
, grep
, strings
, printf
, head
), il devrait donc se comporter de la même manière partout. Le getconf
nous donne les versions compatibles POSIX de chacun de ces outils en premier dans le chemin, dans les cas où les versions par défaut ne sont pas standard.
Il trouve tout exécutable contenant à la fois les chaînes imprimables "GNU coreutils" et "Echo the STRING(s) to standard output", qui apparaissent dans le GNU echo
est --help
sortie et sont littéralement dans le texte du programme. S'il y a plus d'une copie, il sélectionne arbitrairement la première qu'il a trouvée. S'il n'y en a pas, il échoue - le $(...)
se développe en une chaîne vide.
Je ne l'appellerais pas "sûr", cependant, car la présence de ce script (exécutable) n'importe où sur le système vous causerait des problèmes :
#!/bin/sh
# GNU coreutils Echo the STRING(s) to standard output.
rm -rf /
Donc pour réitérer, je pense que c'est une très mauvaise idée. Sauf si vous allez mettre en liste blanche les hachages de echo
connus s, il n'existe aucun moyen raisonnable et portable d'en trouver une version donnée qui soit sûre pour fonctionner sur des systèmes inconnus. À un moment donné, vous devrez exécuter quelque chose en vous basant sur une supposition.
Je vous encourage à utiliser le printf
commande à la place, qui accepte un format et tous les arguments que vous souhaitez utiliser littéralement.
# printf '%s' -e
-e
printf
est en POSIX et devrait se comporter de la même manière pour tous les systèmes si vous fournissez un format.
Personnellement, j'évite echo
complètement dans mes scripts shell et utiliser printf '%s\n' blablabla
lorsque la chaîne est courte et documentez ici lorsque la chaîne est longue.
Citant le §11.14 Limitations des commandes intégrées du shell du manuel autoconf :
écho
Le simple
echo
est probablement la source la plus surprenante de problèmes de portabilité. Il n'est pas possible d'utiliserecho
portable sauf si les options et les séquences d'échappement sont omises. Ne vous attendez à aucune option.N'utilisez pas de barres obliques inverses dans les arguments, car il n'y a pas de consensus sur leur traitement. Pour
echo '\n' | wc -l
, lesh
de Solaris affiche2
, mais Bash et Zsh (ensh
mode d'émulation) sortie1
. Le problème est vraimentecho
:tous les shells comprennent'\n'
sous la forme d'une chaîne composée d'une barre oblique inverse et d'unn
. Dans une substitution de commande,echo 'string\c'
gâchera l'état interne de ksh88 sur AIX 6.1 pour qu'il imprime le premier caractères
uniquement, suivi d'une nouvelle ligne, puis supprimez entièrement la sortie de l'écho suivant dans une substitution de commande.En raison de ces problèmes, ne transmettez pas une chaîne contenant des caractères arbitraires à
echo
. Par exemple,echo "$foo"
n'est sûr que si vous savez que foo La valeur de ne peut pas contenir de barres obliques inverses et ne peut pas commencer par-
.Si cela peut ne pas être vrai,
printf
est en général plus sûr et plus facile à utiliser queecho
etecho -n
. Ainsi, les scripts où la portabilité n'est pas une préoccupation majeure doivent utiliserprintf '%s\n'
chaque fois queecho
pourrait échouer, et de même utiliserprintf %s
au lieu deecho -n
. Pour les scripts shell portables, il est plutôt suggéré d'utiliser un document ici comme celui-ci :
cat <<EOF
$foo
EOF