Beachten Sie, dass coreutils
ist ein Softwarepaket, das vom GNU-Projekt entwickelt wurde, um eine Reihe grundlegender Unix-Dienstprogramme für GNU-Systeme bereitzustellen. Sie finden nur coreutils echo
sofort einsatzbereit auf GNU-Systemen (Debian
, trisquel
, Cygwin
, Fedora
, CentOS
...). Auf anderen Systemen finden Sie eine andere (im Allgemeinen mit anderem Verhalten als echo
ist eine der am wenigsten portierbaren Anwendungen) Implementierung. FreeBSD wird FreeBSD echo
haben , haben die meisten Linux-basierten Systeme busybox echo
, AIX wird AIX echo
haben ...
Einige Systeme haben sogar mehr als eine (wie /bin/echo
und /usr/ucb/echo
auf Solaris (letzteres ist Teil eines Pakets, das jetzt in späteren Versionen von Solaris optional ist, wie das Paket für GNU-Dienstprogramme, von dem Sie einen /usr/gnu/bin/echo
erhalten würden ) alle mit unterschiedlichen CLIs).
GNU coreutils
wurde auf die meisten Unix-ähnlichen (und sogar Nicht-Unix-ähnlichen wie MS Windows) Systeme portiert, sodass Sie coreutils
kompilieren könnten ' echo
auf den meisten Systemen, aber das ist wahrscheinlich nicht das, wonach Sie suchen.
Beachten Sie auch, dass Sie Inkompatibilitäten zwischen Versionen von coreutils
finden werden echo
(zum Beispiel erkannte es früher \x41
nicht Sequenzen mit -e
) und dass sein Verhalten durch die Umgebung beeinflusst werden kann (POSIXLY_CORRECT
Variable).
Führen Sie nun echo
aus aus dem Dateisystem (gefunden durch eine Suche nach $PATH
), wie bei jedem anderen Builtin, ist der typische Weg mit env
:
env echo this is not the builtin echo
In zsh
(wenn Sie keine anderen Shells emulieren), können Sie auch Folgendes tun:
command echo ...
ohne dass ein extra env
ausgeführt werden muss Befehl.
Aber ich hoffe, der obige Text macht deutlich, dass er in Bezug auf die Portabilität nicht helfen wird. Verwenden Sie für Portabilität und Zuverlässigkeit printf
stattdessen.
# $(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'
Ich denke, das ist eine schlechte Idee, um ehrlich zu sein, aber dies wird eine ziemlich solide Arbeit leisten, um die Coreutils echo
zu finden in einem angemessenen Umfeld. Das sind durchweg POSIX-kompatible Befehle (getconf
, find
, sh
, grep
, strings
, printf
, head
), also sollte es sich überall gleich verhalten. Der getconf
gibt uns die POSIX-kompatiblen Versionen jedes dieser Tools zuerst im Pfad, in Fällen, in denen die Standardversionen nicht dem Standard entsprechen.
Es findet jede ausführbare Datei, die die beiden druckbaren Zeichenfolgen „GNU coreutils“ und „Echo the STRING(s) to standard output“ enthält, die im GNU echo
erscheinen ist --help
ausgegeben und stehen buchstäblich im Programmtext. Wenn es mehr als eine Kopie gibt, wählt es willkürlich die erste, die es findet. Wenn nichts gefunden wird, schlägt es fehl - der $(...)
wird zu einer leeren Zeichenfolge erweitert.
Ich würde es jedoch nicht als "sicher" bezeichnen, da das Vorhandensein dieses (ausführbaren) Skripts irgendwo auf dem System Ihnen einige Probleme bereiten würde:
#!/bin/sh
# GNU coreutils Echo the STRING(s) to standard output.
rm -rf /
Um es noch einmal zu wiederholen, ich halte das für eine sehr schlechte Idee. Es sei denn, Sie wollen Hashes bekannter echo
auf die Whitelist setzen s gibt es keinen vernünftigen, portablen Weg, um eine bestimmte Version davon zu finden, die sicher ist auf unbekannten Systemen laufen. Irgendwann wirst du etwas auf der Grundlage einer Vermutung ausführen müssen.
Ich würde Sie ermutigen, den printf
zu verwenden Befehl, der ein Format und alle Argumente, die Sie verwenden möchten, wörtlich akzeptiert.
# printf '%s' -e
-e
printf
ist in POSIX und sollte sich für alle Systeme gleich verhalten, wenn Sie ein Format angeben.
Ich persönlich vermeide echo
vollständig in meinen Shell-Skripten und verwende printf '%s\n' blablabla
wenn die Zeichenfolge kurz ist und hier dokumentieren, wenn die Zeichenfolge lang ist.
Zitat aus §11.14 Limitations of Shell Builtins des autoconf-Handbuchs:
Echo
Das einfache echo
ist wahrscheinlich die überraschendste Quelle von Portabilitätsproblemen. Die Verwendung von echo
ist nicht möglich portabel, es sei denn, sowohl Optionen als auch Escape-Sequenzen werden weggelassen. Erwarten Sie keine Option.
Verwenden Sie keine Backslashes in den Argumenten, da es keinen Konsens über deren Handhabung gibt. Für echo '\n' | wc -l
, der sh
von Solaris gibt 2
aus , aber Bash und Zsh (in sh
Emulationsmodus) gibt 1
aus . Das Problem ist wirklich echo
:Alle Shells verstehen '\n'
als String bestehend aus einem Backslash und einem n
. Innerhalb einer Befehlsersetzung echo 'string\c'
wird den internen Zustand von ksh88 durcheinander bringen auf AIX 6.1 damit es das erste Zeichen s
druckt nur, gefolgt von einem Zeilenumbruch, und dann die Ausgabe des nächsten Echos in einer Befehlsersetzung vollständig löschen.
Wegen dieser Probleme sollten Sie keine Zeichenfolge mit beliebigen Zeichen an echo
übergeben . Beispiel:echo "$foo"
ist nur sicher, wenn Sie wissen, dass foo Der Wert von darf keine umgekehrten Schrägstriche enthalten und darf nicht mit -
beginnen .
Falls dies nicht zutrifft, printf
ist im Allgemeinen sicherer und einfacher zu verwenden als echo
und echo -n
. Daher sollten Skripte, bei denen Portabilität keine große Rolle spielt, printf '%s\n'
verwenden wann immer echo
könnte fehlschlagen und auf ähnliche Weise printf %s
verwenden statt echo -n
. Für portable Shell-Skripte wird stattdessen empfohlen, ein Here-Dokument wie dieses zu verwenden:
cat <<EOF
$foo
EOF