POSIX defines echo as only taking string parameters and no options, but notes that behaviour facing `-n` is implementation-defined.
BSD and GNU echo implement `echo -n` as not printing a trailing newline, but `echo` commonly calls to a shell builtin which may or may not follow that behaviour (and may switch behaviour depending on whether the shell is in "sh mode" or not), so `echo -n` could print `-n<newline>` or nothing whatsoever (empty string and suppressed newline) depending on the utils set, the shell, and the shell's runmode.
GNU echo also supports -e, -E, --version and --help options, and much like -n shells and other utils set may or may not support these.
For instance on my machine (OSX 10.11)
* zsh (builtin) interprets -e, -E and -n as options (but not version or help)
* bash (builtin) also does, except when invoked as sh in which case it does not and all parameters are literal (this may also apply to zsh)
* dash (builtin) interprets -n, but none of the others. bash note may also apply to it.
* BSD echo interprets -n but will print -e, -E, version and help literally
* GNU echo interprets all of the above
So if you use echo with any non-literal parameter, or with one of the parameters listed above, in a script you distribute to un-controlled third-parties as an sh script (rather than e.g. a bash or zsh script specifically) you will suffer from portability issues.
And that's just for measly trivial echo (and incidentally why you should always use printf rather than echo in scripts you try to make portable).
The only operating systems that are certified to conform to POSIX are old Unix operating systems. GNU has always been non-POSIX. And honestly, a POSIX implementation would be more trouble than it's worth.
The point of coreutils is to have utilities that make up the ability to write scripts for and interact with your operating system, right? Well, what operating system?? A POSIX-compliant one? Or just a mostly-POSIX-compliant one? Or one with POSIX extensions? How would your utilities know the difference? How would the OS know how to deal with these utilities? Would the user know the difference?
Ultimately, each platform has quirks, and it is up to the developer to port and test their script or application to a platform and make any necessary changes. This extends to far more than just POSIX compliance.
That's not a question of certification or extensions, I'm talking about being able to write portable scripts. Due to the interaction between its definition and its extensions, echo is a prime example of being impossible to use portably (except in the very restricted case of only literal strings without escapes which don't start with a -).
> Ultimately, each platform has quirks, and it is up to the developer to port and test their script or application to a platform and make any necessary changes.
That is not humanly feasible and that's why specifications exists. You can't "port and test" your script to a platform which doesn't even exist yet, but if you follow the specification and the platform implements it (assuming it does so correctly) your scripts will run.
Ok, I think I understand the confusion now. You seem to be of the impression that shell scripts are like bytecode executed in a virtual machine. That is the only way I know of that you could write an application for a platform that doesn't exist and expect it to work. But even for that to work, it would need to be the same VM, and bytecode generated by & for it, or there's still no guarantee it will work.
Of course, you can already write a shell script for a particular shell, distribute that shell to that system, and depend on the shell to properly execute your script [by using internal functions only]. But that defeats the whole purpose of following a standard like POSIX, or caring at all how any given platform's 'echo' program works.
Bottom line, though: two independent implementations of a standard provide no guarantee they will work together. Practice over a couple decades shows this to be the case.
> Ok, I think I understand the confusion now. You seem to be of the impression that shell scripts are like bytecode executed in a virtual machine.
What in bloody hell are you talking about?
> Of course, you can already write a shell script for a particular shell
Which is irrelevant to my comment as that's not what portability means.
> But that defeats the whole purpose of following a standard like POSIX
Exactly.
> Bottom line, though: two independent implementations of a standard provide no guarantee they will work together.
If following a standard can't ensure your program can work on two different implementations of the standard, you don't have a standard you have decorated toilet paper.
Which is more or less what the "commands and utilities" part of POSIX is.
ECHO(1) FreeBSD General Commands Manual ECHO(1)
NAME
echo — write arguments to the standard output
For this definition, -n should mean merely a sequence of two bytes to be written to stdout. Why not just use printf instead? It is way more flexible and powerfull, and "printf x" always prints "{'x', 0}";.
The POSIX spec is basically the minimal intersection of all commercial UNIX distros of its day. It defines a minimal system that happened to be what everybody already had implemented. For the most part you are allowed to add features to a POSIX base to make a real OS, since that's what everybody had.
This is also why the old Windows POSIX subsystem was so useless. It implemented only the minimal amount needed to check off the box on a feature list, and none of the stuff you need to actually make a system usable.
That said, POSIX has a fair bit of braindamage baked in and people can be excused for ignoring the worst parts and instead doing the right thing.
POSIX defines echo as only taking string parameters and no options, but notes that behaviour facing `-n` is implementation-defined.
BSD and GNU echo implement `echo -n` as not printing a trailing newline, but `echo` commonly calls to a shell builtin which may or may not follow that behaviour (and may switch behaviour depending on whether the shell is in "sh mode" or not), so `echo -n` could print `-n<newline>` or nothing whatsoever (empty string and suppressed newline) depending on the utils set, the shell, and the shell's runmode.
GNU echo also supports -e, -E, --version and --help options, and much like -n shells and other utils set may or may not support these.
For instance on my machine (OSX 10.11)
* zsh (builtin) interprets -e, -E and -n as options (but not version or help)
* bash (builtin) also does, except when invoked as sh in which case it does not and all parameters are literal (this may also apply to zsh)
* dash (builtin) interprets -n, but none of the others. bash note may also apply to it.
* BSD echo interprets -n but will print -e, -E, version and help literally
* GNU echo interprets all of the above
So if you use echo with any non-literal parameter, or with one of the parameters listed above, in a script you distribute to un-controlled third-parties as an sh script (rather than e.g. a bash or zsh script specifically) you will suffer from portability issues.
And that's just for measly trivial echo (and incidentally why you should always use printf rather than echo in scripts you try to make portable).