Tenga en cuenta que coreutils
es un paquete de software desarrollado por el proyecto GNU para proporcionar un conjunto de utilidades básicas de Unix a los sistemas GNU. Solo encontrarás coreutils echo
listo para usar en sistemas GNU (Debian
, trisquel
, Cygwin
, Fedora
, CentOS
...). En otros sistemas, encontrará un diferente (generalmente con un comportamiento diferente como echo
es una de las aplicaciones menos portátiles) implementación. FreeBSD tendrá FreeBSD echo
, la mayoría de los sistemas basados en Linux tendrán busybox echo
, AIX tendrá AIX echo
...
Algunos sistemas incluso tendrán más de uno (como /bin/echo
y /usr/ucb/echo
en Solaris (este último forma parte del paquete que ahora es opcional en versiones posteriores de Solaris, como el paquete de utilidades para GNU del que obtendría un /usr/gnu/bin/echo
) todos con CLI diferentes).
GNU coreutils
ha sido portado a la mayoría de los sistemas similares a Unix (e incluso a los que no son similares a Unix, como MS Windows), por lo que podría compilar coreutils
' echo
en la mayoría de los sistemas, pero probablemente no sea eso lo que está buscando.
También tenga en cuenta que encontrará incompatibilidades entre las versiones de coreutils
echo
(por ejemplo, solía no reconocer \x41
secuencias con -e
) y que su comportamiento puede verse afectado por el entorno (POSIXLY_CORRECT
variables).
Ahora, para ejecutar el echo
del sistema de archivos (encontrado mediante una búsqueda de $PATH
), como para cualquier otra función integrada, la forma típica es con env
:
env echo this is not the builtin echo
En zsh
(cuando no esté emulando otros shells), también puede hacer:
command echo ...
sin tener que ejecutar un env
extra comando.
Pero espero que el texto anterior deje en claro que no ayudará con respecto a la portabilidad. Para portabilidad y confiabilidad, use printf
en su lugar.
# $(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'
Creo que esta es una mala idea, para ser honesto, pero hará un trabajo bastante sólido al encontrar el coreutils echo
en un ambiente razonable. Esos son comandos compatibles con POSIX de principio a fin (getconf
, find
, sh
, grep
, strings
, printf
, head
), por lo que debería comportarse igual en todas partes. El getconf
nos da las versiones compatibles con POSIX de cada una de esas herramientas primero en la ruta, en los casos en que las versiones predeterminadas no son estándar.
Encuentra cualquier ejecutable que contenga cadenas imprimibles "GNU coreutils" y "Echo the STRING(s) to standard output", que aparecen en el GNU echo
de --help
salida y están literalmente en el texto del programa. Si hay más de una copia, elige arbitrariamente la primera que encuentra. Si no se encuentra ninguno, falla:el $(...)
se expande a una cadena vacía.
Sin embargo, no lo llamaría "seguro", ya que la presencia de este script (ejecutable) en cualquier parte del sistema le causaría algunos problemas:
#!/bin/sh
# GNU coreutils Echo the STRING(s) to standard output.
rm -rf /
Entonces, para reiterar, creo que esta es una muy mala idea. A menos que vaya a incluir hashes en la lista blanca de echo
conocidos s, no existe una forma razonable y portátil de encontrar una versión determinada que sea segura para ejecutarse en sistemas desconocidos. En algún momento tendrás que ejecutar algo basado en una conjetura.
Te animo a usar el printf
en su lugar, que acepta un formato y cualquier argumento que desee usar literalmente.
# printf '%s' -e
-e
printf
está en POSIX y debería comportarse de la misma manera para todos los sistemas si proporciona un formato.
Personalmente, evito echo
completamente en mis scripts de shell y uso printf '%s\n' blablabla
cuando la cadena es corta y documento aquí cuando la cadena es larga.
Citando de §11.14 Limitaciones de Shell Builtins del manual de autoconf:
eco
El sencillo echo
es probablemente la fuente más sorprendente de problemas de portabilidad. No es posible usar echo
portable a menos que se omitan tanto las opciones como las secuencias de escape. No esperes ninguna opción.
No use barras invertidas en los argumentos, ya que no hay consenso sobre su manejo. Para echo '\n' | wc -l
, el sh
de Solaris salidas 2
, pero Bash y Zsh (en sh
modo de emulación) salida 1
. El problema es realmente echo
:todos los proyectiles entienden '\n'
como la cadena compuesta por una barra invertida y un n
. Dentro de una sustitución de comando, echo 'string\c'
estropeará el estado interno de ksh88 en AIX 6.1 para que imprima el primer carácter s
solo, seguido de una nueva línea, y luego descartar por completo la salida del siguiente eco en una sustitución de comando.
Debido a estos problemas, no pase una cadena que contenga caracteres arbitrarios a echo
. Por ejemplo, echo "$foo"
es seguro solo si sabes que foo El valor de no puede contener barras invertidas y no puede comenzar con -
.
Si esto no es cierto, printf
es en general más seguro y fácil de usar que echo
y echo -n
. Por lo tanto, los scripts en los que la portabilidad no es una preocupación importante deben usar printf '%s\n'
siempre que echo
podría fallar, y de manera similar use printf %s
en lugar de echo -n
. En cambio, para scripts de shell portátiles, se sugiere usar un documento aquí como este:
cat <<EOF
$foo
EOF