Where shell script portability falls down is often in the need to call external utilities. Once you move beyond a common set of basic functionalities, many unix tools will vary in their behaviour. E.g. find, make, tar, ps, even ls vary from platform to platform. Even if your script is written portably, you have to take account of the variance of the tools the script calls.
I recall one script that broke because ls on one system put an extra leading space in its output. (I think it was an old sgi box.)
Yes, there is posix. So if you must write scripts, try to stick to that. But I have some systems here that are pretty old, and I can't be sure that they are posix compliant.
When I have to use unix tools, I try to arrange for the gnu utilities to be built and installed, so I only have to consider one set of man pages, and not a set for each platform the script has to run on. Similarly, makefile portability is difficult because make behaviour varies between platforms e.g. vpath, so I try to arrange for gnu make to be installed.
In response to those people who just shell out from python: that's a method that I have seen a few times among programmers transitioning from shell to python scripting, including myself. You end up with a bash script where every line is wrapped with os.popen calls. No, the way to write a python script is to look in the library doco for the modules that have the functionality you want. As someone pointed out, find -> os.walk for example. Plus os.popen or os.subprocess from python is still vulnerable to the non-portability that results from behaviour variation of unix tools across platforms.
My preference these days is to write scripts in python, but I agree that there will be systems without python, where shell is required. In those cases, it is great to know how write scripts with better portability, so the book in the post is likely a good addition to the library.