Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Bourne Shell Programming on Windows

187 views
Skip to first unread message

TAM

unread,
Jun 22, 2003, 12:06:42 PM6/22/03
to
Hi,

I was wondering if there is any program (e.g. Cygwin) that will allow me to
do learn Bourne shell programming on Windows 2000 Pro.

Thanx

TAM


Walt Fles

unread,
Jun 22, 2003, 3:58:24 PM6/22/03
to
It comes with kornshell I thought, which is a much improved version over
bourne shell

"TAM" <tmphot...@shaw.ca> wrote in message
news:mukJa.286958$Vi5.7...@news1.calgary.shaw.ca...

Peter S Tillier

unread,
Jun 23, 2003, 2:24:25 AM6/23/03
to
[[Top posting corrected ... ]]
Walt Fles wrote:

> "TAM" <tmphot...@shaw.ca> wrote in message
> news:mukJa.286958$Vi5.7...@news1.calgary.shaw.ca...
>> Hi,
>>
>> I was wondering if there is any program (e.g. Cygwin) that will
>> allow me to do learn Bourne shell programming on Windows 2000 Pro.
>>
>> Thanx
>>
>> TAM
> It comes with kornshell I thought, which is a much improved version
> over bourne shell
>

No, Cygwin comes with bash, ash (a Bourne clone), pdksh, tcsh, zsh,
depending upon which you decide to install.
--
Peter S Tillier
"Who needs perl when you can write dc, sokoban,
arkanoid and an unlambda interpreter in sed?"

Dan Mercer

unread,
Jun 23, 2003, 9:47:52 AM6/23/03
to

"Peter S Tillier" <peter_...@despammed.com> wrote in message news:bd66er$ndv$1$8302...@news.demon.co.uk...
: [[Top posting corrected ... ]]

: Walt Fles wrote:
:
: > "TAM" <tmphot...@shaw.ca> wrote in message
: > news:mukJa.286958$Vi5.7...@news1.calgary.shaw.ca...
: >> Hi,
: >>
: >> I was wondering if there is any program (e.g. Cygwin) that will
: >> allow me to do learn Bourne shell programming on Windows 2000 Pro.
: >>
: >> Thanx
: >>
: >> TAM
: > It comes with kornshell I thought, which is a much improved version
: > over bourne shell
: >
:
: No, Cygwin comes with bash, ash (a Bourne clone), pdksh, tcsh, zsh,
: depending upon which you decide to install.

But ksh93 is also available from www.kornshell.com

Dan Mercer
dme...@mn.rr.com

: --

:


Walt Fles

unread,
Jun 23, 2003, 10:04:27 AM6/23/03
to
Korn Shell 93 ROCKS!
It is far superior from bash or bourne.

I used to work with Dave Korn so I sort of know!

While you're downloading korn shell, check out the rest of the AST tool kit
from:
http://www.research.att.com/sw/download/

nmake is far superior to ANT, make, or gmake, and is much more easily
extensible

"Dan Mercer" <dme...@mn.rr.com> wrote in message
news:cyDJa.45693$fe.8...@twister.rdc-kc.rr.com...

Klaus Horsten

unread,
Jun 23, 2003, 10:49:30 AM6/23/03
to
> I was wondering if there is any program (e.g. Cygwin) that will allow me to
> do learn Bourne shell programming on Windows 2000 Pro.

I think you mean BASH.

Just download cygwin. You don't have to use it.

Make e.g. a D:/bin path.
Register the path so that windows finds the files.
Copy the bash.exe of cygwin/bin into your bin.
Sart cmd.exe.
Type bash.
You will get an error.
Just give him the dll he wants from cygwin (drop it in your bin).
Than start dropping all the exes you need in your bin path - take it
from cygwin or from:

http://www.cam.hi-ho.ne.jp/~mttm/win_unix.html
http://gnuwin32.sourceforge.net/packages.html

For me it makes sense to learn bash without learning cygwin.
You can use many dos-tools also with bash.

Here are some good scripts:
http://www.shelldorado.com/scripts/commands.html

One thing:
start bash with bash --login
Than you can use the .profile-file under c:\
This is very important. Learn about the .profile-file, look where
cygwin drops it, use this or make your own. It makes very easy.


Hope this helps

Klaus

Peter S Tillier

unread,
Jun 24, 2003, 2:26:41 AM6/24/03
to
Dan Mercer wrote:
> "Peter S Tillier" <peter_...@despammed.com> wrote in message
> news:bd66er$ndv$1$8302...@news.demon.co.uk...
>: [[Top posting corrected ... ]]
>: Walt Fles wrote:
>:
>: > "TAM" <tmphot...@shaw.ca> wrote in message
>: > news:mukJa.286958$Vi5.7...@news1.calgary.shaw.ca...
>: >> Hi,
>: >>
>: >> I was wondering if there is any program (e.g. Cygwin) that will
>: >> allow me to do learn Bourne shell programming on Windows 2000 Pro.
>: >>
>: >> Thanx
>: >>
>: >> TAM
>: > It comes with kornshell I thought, which is a much improved version
>: > over bourne shell
>: >
>:
>: No, Cygwin comes with bash, ash (a Bourne clone), pdksh, tcsh, zsh,
>: depending upon which you decide to install.
>
> But ksh93 is also available from www.kornshell.com
>
> Dan Mercer
> dme...@mn.rr.com
[...]

Indeed it is. I was pointing out that it isn't one of the Cygwin
packages that is directly available as binary. The default supplied
shell with Cygwin is bash. You can certainly compile ksh93 under
Cygwin.

llewelly

unread,
Jun 24, 2003, 1:18:31 PM6/24/03
to
ema...@gmx.net (Klaus Horsten) writes:
[snip]

> For me it makes sense to learn bash without learning cygwin.
[snip]

I suspect this doesn't make sense for most people; most
non-trivial shell-scripting examples in books and in availible
working source rely extensively on basic unix file and text
utilities.

> You can use many dos-tools also with bash.

This is true.

Stephane CHAZELAS

unread,
Jun 25, 2003, 4:51:19 AM6/25/03
to
Walt Fles wrote:
> Korn Shell 93 ROCKS!
> It is far superior from bash or bourne.
[...]

I see more and more often in this newsgroup enthusiastic posts about the
ksh93 shell. I'd like to temper it a bit. I consider ksh and especially
ksh93 one of the worst shell ever written, and especilly, its claim to
be a good choice for a programming language is ridiculous. By no mean
can it be compared to interpreted languages like perl/python/ruby/tcl.

Making complex applications with it is probably the worst choice
possible. Below are some unsorted arguments that come to my mind for
what I say. Note that some of them also apply to other Bourne like
shells like bash or zsh or to shells in general.

Note that few apply to zsh. However, zsh never claimed to be a
programming language. I'd rather say that it's a powerfull interactive
shell with a powerful extension language, such as vim is a powerful
editor with perl as an extension language, but you don't write vim
scripts (even if it's possible), you write vim modules for use within
vim.

This post is also a followup to detail the warnings I post from time to
time in this newsgroup about "shell programming being considered
harmful" (slrna7b24n.ae.s...@pcchazelas.free.fr
slrnaf52a8.98.s...@pcchazelas.free.fr
3dbfddac$0$5099$626a...@news.free.fr
slrnb1gtla.5g.s...@pcchazelas.free.fr
3dfeed96$0$2141$626a...@news.free.fr
slrnb299sn.10l.s...@pcchazelas.free.fr
slrnatcvmq.a4.s...@pcchazelas.free.fr
slrnb2m1un.pn.s...@pcchazelas.free.fr
slrnb2t025.lg.s...@pcchazelas.free.fr
slrnb5eohu.ue.s...@pcchazelas.free.fr
slrnbafctr.48.s...@pcchazelas.free.fr, for example)

1- Poor design.

The problem is that it tried to keep some Bourne shell
/compatibility/, not in the best way. ksh93 inherits from ksh88
which inherits from Bourne shell. It kept the most annoying
"features" of sh and brought new ones. Too bad that POSIX standard
for sh was based on a great part of ksh88. Now, we encounter many of
ksh design awkwardnesses in most shells

2- * is either '*' or a list of files

echo *** title ***
will output "*** title ***" only if there's no file in the current
directory.

for file in *
will loop through files in the current directory. But you'll have a
nasty effect if there's no file.

Worse:
rm file.[cC]
removes any of a file.c or file.C file if they exist. But, if they
don't, a file named "file.[cC]" might be unintentionnally removed.

That makes globbing hard to use reliably and force you to quote
everything in case it could be considered as a file pattern when you
don't want it to. This is such an annoying feature that one could
consider it as a bug (see zsh for a correct behavior).

As an example http://www.research.att.com/~dgk/ksh/script/env (on
David Korn's home page) contains "getopts '[-]' opt --???man".
--???man is a wildcard and David forgot to quote it. So if there's a
file named "--batman" in the current directory, his script will be
broken.

ksh93 introduced many new globbing operators. So, for each character
you type, you have to be careful it's not a globbing operator.

So, to be sure, you should quote every word. But you can't quote
keywords. You have to perfectly know the syntax of ksh to be able to
use it reliably (did you know "while" was a keyword while "break"
was a builtin?). It has that many corner cases that its almost
impossible. Look at David Korn's himself ksh scripts on its home
page, most contain numerous flaws even the shortest ones.

3- $var is either a pattern or a list or a string or combination of
those despite ksh93 has array type variables.

ksh93 has arrays, you can do

list=("file 1" "file 2")
for file in "${list[@]}"; do
something with "$file"
done

So, the old Bourne
list="file 1,file 2" IFS=,
set -f
for file in $list; do
...
done

should no longer be necessary. But ksh decided to keep the bourne
compatibility. Consequence is that you need to quote every *string
type* variable so that it is not considered as a Bourne like list or
a globbing pattern (or you must issue a "IFS=; set -f" at the
beggining of the script).

Each time you want to split a string, you have to disable filename
generation (on by default).

This may also be considered as a bug (see zsh for a correct way).

4- cryptic syntax.

copying two arrays is:

set -A new_array -- "${old_array[@]}"

compare with rc:
new_array = $old_array

or zsh:
new_array=($old_array)

read the (not fully documented) getopts builtin man page and laugh.

no consistant variable expansion syntax: various non-intuitive
operators of different shape. Hard to know wether/how they can be
combined.

corner cases everywhere. word splitting was originally designed to
make the shell user life easier in most cases. For an interactive
use, you generally don't have to worry, it works. However, if you
want to consider ksh as a programming language and use word
splitting for text splitting, you have to know in details how it
works. Check at
www.opengroup.org/onlinepubs/007904975/utilities/xcu_chap02.html#tag_02_06_05
and cry... ksh syntax is full of corner cases, for many variable
expansion operators, there are various quoting/escaping
mechanisms... Compare the "rc" man page and the "ksh93" man page.

You can read and understand "rc" man page in less than one hour. You
can be an efficient "rc" programmer and write acceptably reliable rc
scripts in one day. Who can pretend he can write reliable ksh
scripts?

5- command substitution removes too many NLs

Usual commands display the value they have to display followed by a
newline character. Because they display them on a text line and a
text line is terminated by a NL character on Unix.

for instance, "basename a/b" outputs "b\n"

To store the value returned by that command in a variable, you must
remove that trailing NL. That's what command substitution does,
except that instead of removing the trailing NL, it removes *every*
trailing NL (even those that are part of the value returned by the
command).

So, you'd think

print -r -- "$(cmd)"
outputs the same as
cmd

It doesn't, except when the value returned by the command doesn't
end with a newline character.

To work around this, you have to do:
var=$(cmd; echo .)
var=${var%?} var=${var%?}

6- danger of using a shell both as a shell and as a programming
language.

Historically, you made shell "scripts" not programs, i.e. you put a
sequence of command in a file so that you don't have to type it each
time.

But when putting the sequence of commands you'd have typed in a
file, you forget to put another very important thing in it: your
brain. When you use the shell interactively, there's processing done
by the shell and the command it runs, but also by your mind.

After each command you type, you observe the result and take the
decision to run or not this or that next command (or even to
interrupt a command when it is going to behave incorrectly).

When in a script, who will check the command ran correctly?

When you write a C program, you always do things like this:

if (chdir(variable) < 0) {
perror("chdir");
exit(1);
}

In a shell, most forget to do
cd -- "$var" || exit
because they are used to only typing
cd $var
at the prompt and look at the result.

Moreover, commands are often made to be run interactively. The
information on failure is a text intended for a human on standard
error. So, generally, a script will be unable to parse that error
message to take appropriate action.

That's one of the most important reasons why a shell shouldn't be
seen as a programming language.

7- read/print do extra processing by default

from a programming language, you'd expect ways to read data into a
variable, and output the content of a variable.

The usual commands to do this (read, print, echo) fail to do it
reliably when not passed specific options. Default behavior of read
or print are to perform extra processing on the value read or
written.

If you want to read a line of input, it's
IFS= read -r variable
If you want to write the content of a variable, it's

print -r -- "$variable"
or
echo "${variable//\\/\\\\}"
(provided that for some obscur reason, for example the content of
the PATH variable, echo doesn't recognize options)

8- "--" necessary

In shell language, there are few statements, most of the processing
is performed by commands (builtin or not). Commands take operators
and operands as in every language except that in shell operands and
operators are both arguments. The way you distinguish them can be
there position on the command line, or their content. For exemple,
an argument located after the command name and starting with a dash
will be an option (an operator lets say) while one not starting with
a dash and placed after an option that expects an argument will be
an operand (data).

Ok, but what happens if the data starts with a dash. What if I want
to go in the "-P" directory?

cd -P # and I silently go in my home directory instead
# of the -P one (because -P is taken as an option to cd).

If I where at shell prompt, I would have realized it would cause a
problem, or at least, I would have realized afterwards that I was
not in the "-P" directory (for example because my prompt displays
the current working directory). So I would have used cd ./-P
instead.

But, in a script, if I put
cd "$1" && rm -f *
where "$1" is a user provided directory. Suppose "$1" is "-P", and
the first file in your home directory is named "-r". This command
resolves to:

cd -P && rm -f -r every file and dir in your home directory

For most commands, there's a work around: the "--" argument to
separate options from arguments. So the command line above is best
written:

cd -- "$1" && rm -f -- *

The problem is that some commands don't accept that syntax, and it
can't be applied to some others because they have not the shape:
command [options] arguments

Examples are find, test ([), expr.

So, for a filename, you can do awkward things like:

case $var in
/*) ;;
*) var=./$var;;
esac
find "$var" ...

9- can't handle binary data

Mostly because, as a shell, ksh has to call execle(2) to make a task
done by some external utility, it can't pass a '\0' character to
them, and also because some of its variables are mapped to
environment variables. Even when not calling external utilities, ksh
is unable to store a '\0' in its variable. So, it's unable to
process binary data, except through a transformation format
(uuencode, ansi C escapes, quoted printable...) which makes life yet
harder for the developper (note that zsh is the only shell that can
cope with '\0').

It's also unable to cope with GNU find -print0 or grep/sort -z
output.

10- no way to do word splitting on spaces so that empty elements are
allowed. Because SPC, TAB, NL are /IFS white space characters/

in:
string=" field2 field3 field5 "
if you want to consider a *single* space as the separator, there are
7 fields, 4 of which are empty (1st, 4th, 6th, 7th)

If you do:
IFS=" "; set -f
array=($string)

You get 3 elements into $array. A solution to work around this is:

tmp=${string//_/_u}
tmp=${tmp//,/_c}
IFS=,
set -f
array=($tmp)
array=("${array[@]//_c/,}")
array=("${array[@]//_u/_}")

It's even more clumsy for a NL separated list (which occurs much
often).

11- behavior of a script depends on its name!

cd /tmp
PATH=$PATH:
echo '#! /usr/local/bin/ksh93' > script.ksh
chmod 755 script.ksh
ln -s script.ksh ./--man
ln -s script.ksh ./-i

"script.ksh", "-i" and "--man" are supposed to be the same script.
However, the first one does nothing, the second runs an interactive
shell, and the third one displays a short ksh93 man page!

Work around is to use:
#! /usr/local/bin/ksh93 -

12- Documentation.

ksh93 documentation is disseminated. The man page doesn't describe
half of the behavior. To know about a builtin, you have to run ksh93
and issue the (undocumented):

builtin --man
or
builtin --help
or
builtin --html
(yes all the documentation is in the binary ksh93 executable! This
certainly goes against most system documentation policy)

That doesn't work with every builtin (echo, :), and for keywords
(for, while...). At least, even if it's arguable to put the
documentation in the code, bash chose a dedicated builtin for that
(help) and has a full man/info/html page.

13- Poor interactive shell

shell vocation is to be used at prompt. ksh93 is one of the most
poorly featured one: no programmed (or even programmable)
completion, no incremental search, poor history facilities, poor
extended key handling, poor prompt facilities, no multiline command
editing, no spelling correction, no rc file except via the dumb ENV
variable processing (shared with other shells, so shouldn't be used,
or used with care)

14- undocumented features, behaviors:

syntax: typeset, export are said to be "shell builtins", but their
parsing is different from other builtins (they are not simple
commands, but kind of assignments mixed with arguments where
redirections are allowed, it's not clear in which position on the
command line assignment are allowed and there scope may vary depending
on that):

$ echo -A a=(aze)
ksh93: syntax error: `(' unexpected
$ typeset -A a=(aze)
$

word splitting is only performed in some cases:

$ vars="a=1 b=2 c=3" IFS=" "; set -f
$ export $vars
$ env | grep '^[abc]='
a=1
b=2
c=3

$ vars="1 b=2 c=3" IFS=" "; set -f
$ export a=$vars
$ env | grep '^[abc]='
a=1 b=2 c=3

same for filename generation with typeset or export (bash copied that
behavior)

for i in 1 2
{
print -r -- "$i"
}

statement works and is not documented. Problem with undocumented
features is that you can use them but you are not guaranteed they
will be in the next version.

15- approximate syntax permitted:

unmatched quotes permitted in some cases:
a=`echo "a`
b="`echo b"
c="`echo \"" # $c empty
...

fuzzy syntax.

{ (( 0 )) }
{ ( false ) }
are allowed

{ false }
not ("}" is a keyword so must start a new command, but still is
allowed after ")").


16- arithmetic expansion that depends on locale

#! /usr/local/bin/ksh93 -
typeset -F pi=3.14159265359
echo "cos(pi/2) is $(( cos(pi/2) ))"

when run in a french locale gives:

ksh93: .[2]: typeset: 3.14159265359: arithmetic syntax error
because in french, the decimal point is a comma.

17- "export var" when var is unset doesn't put "var" in the environment.

18- 010 and 08 and 008 are 8... sometimes

$ typeset -Z3 i=008 j=010
$ echo $i $j
008 010
$ typeset -i i j
$ echo $i $j
8 10
$ typeset -i i=008 j=010
$ echo $i $j
8 8
$ typeset -Z3 i j
$ echo $i $j
008 008

This is really annoying when dealing with dates:

19- arrays start at index 0

Bourne shell had one array (one global and one per function
actually): the positional parameters ($@). You could fill it with

set -- "value 1" "value 2"

With ksh93, you fill an array with

set -A array -- "value 1" "value 2"

With Bourne shell, you put "value 1" in element of indice 1, with ksh
arrays, you start with 0 ($1 would be ${@[0]})

20- two (sometime compatible) ways to access array elements.

${array[@]:3:1} and ${array[3]} are the same
except in the (not so usual) case where element indices are not
contiguous or don't start at 0

To obtain a slice of an array, you can do
slice=("${array[@]:first:number}")

But again, "first" is not an array index, it's the position number in
the list.

To obtain the slice for index 3 to index 7, you have to do:
slice=()
for i in "${!array[@]}"; do
(( i >= 3 && i <= 7 )) && slice=("${slice[@]}" "${array[i]}")
done

Compare with "es":

slice = $array(3...7)
"es" guarantees indices to be contiguous and start at 1.

or zsh:

slice=($array[3,7])

21- conflict between ${var:-default} and ${var: -1}
${var:0} is the first char in "$var", i=-1, ${var:i} is the last
char in "$var", but ${var:-1} is $var or "1" if it's empty (as in
Bourne shell). Why didn't ksh use a construct like ${var[i..j]} to
be consistant with array subscripting, instead of that confusing
${var:offset:length}?

note that
var="101 reason to avoid ksh"
echo ${var:#10}
echo ${var:2#10}
give the same result (with ksh88 and ksh93o only).

22- confusing versionning policy
The 93 is only the year of the first release of that branch of ksh.
A script working with one ksh93, will not necessarily work with
another ksh93, you've got to know the release letter (latest as of
this writing is "o")

23- ksh93 is not open source in the OSI meaning of it

24- exit status policy different from any other shell's

$? contains 256 + signum when a command was killed instead of 128 +
signum in every other shell.

In conclusion, it might be possible for one knowing in details the ins
and outs of ksh and the common traps of shell programming to write
reliable ksh scripts. But, if you apply all the work arounds I showed
above, I guess you see how illegible and unmaintainable a /correct/
script would be.

ksh93 comes with features that could appear useful for a programming
language (pre-compilation, inline documentation, TCP socket support,
disciplines (I've yet to see what it can be useful to), kind of regular
expressions, math library function...), but they are brought over a
really broken basis. You don't build a spaceship on top of a bicycle
frame!

Thanks for reading, feel free to argue on all this. Of course, I exposed
only the arguments *against* writing shell scripts. There are toward
writing scripts in some circumstances, but generally not with the ksh93
shell.

--
Stéphane

Stephane CHAZELAS

unread,
Jun 25, 2003, 6:10:50 AM6/25/03
to
Stephane CHAZELAS wrote:
[...]

> 10- no way to do word splitting on spaces so that empty elements are
> allowed. Because SPC, TAB, NL are /IFS white space characters/
>
> string=" field2 field3 field5 "
[...]

> You get 3 elements into $array. A solution to work around this is:
>
> tmp=${string//_/_u}
> tmp=${tmp//,/_c}
> IFS=,
> set -f
> array=($tmp)
> array=("${array[@]//_c/,}")
> array=("${array[@]//_u/_}")
[...]

Should be:

tmp=${string//_/_u}
tmp=${tmp//,/_c}
tmp=${tmp// /,}


IFS=,
set -f
array=($tmp)
array=("${array[@]//_c/,}")
array=("${array[@]//_u/_}")

Sorry. But still, as I've just discovered, it's broken with
ksh93.

var='a,b,' IFS=','
set -f; set -- $var
echo "$#"

gives "2" instead of the expected (as of POSIX) "3". The bug is
also in bash.

So the work around becomes:

tmp=${string//_/_u}
tmp=${tmp//,/_c}
tmp=${tmp// /,},z
IFS=,
set -f
array=($tmp)
unset array[${#array[@]}-1]


array=("${array[@]//_c/,}")
array=("${array[@]//_u/_}")

--
Stéphane

Stephane CHAZELAS

unread,
Jun 25, 2003, 7:10:36 AM6/25/03
to
Stephane CHAZELAS wrote:
[...]

> var='a,b,' IFS=','
> set -f; set -- $var
> echo "$#"
>
> gives "2" instead of the expected (as of POSIX) "3". The bug is
> also in bash.
[...]

Well that's somehow consistant and could be considered more
as a feature than as a bug.

if "," is considered as a field "terminator" rather than a
field separator, you're able to make the distinction between an
empty array and an array with one empty element, not otherwise.

For instance:

list1="," would be a list with 1 empty element if "," is a field
terminator, with 2 elements if "," is a field separator.

list="" would be an empty list if "," is a field terminator but
we'd have to decide wether it's an empty list or a list with one
element if "," is a field separator. The work around I give
says it's a list with one element and there's no way to
represent an empty list with a string in that model.

--
Stéphane

David Thompson

unread,
Jun 25, 2003, 1:51:57 PM6/25/03
to
"Stephane CHAZELAS" <stephane...@yahoo.fr> wrote

> I consider ksh and especially ksh93 one of the worst
> shell ever written, and especilly, its claim to be a
> good choice for a programming language is ridiculous.
> By no mean can it be compared to interpreted languages
> like perl/python/ruby/tcl.

[snip]

Say it ain't so! ;)

Shell programming is what it is, baggage and all. It is quick
and useful and has grown with the times. IMHO, ksh has done an
admirable job in an unforgiving world where the successful
programs can only grow in ways that maintain backwards
compatibility with their installed bases.

The thing I put into perspective is that Unix allows almost
any character to be part of a filename. This great freedom
comes at a price when tools designed to be so close to the
file system (such as shells) must navigate and manipulate it.
So, for me, filenames with spaces, newlines, tabes, colons,
dashes (esp if they begin with dashes), asterisks, etc, are
just plain trouble and should be considered broken.

Of course, my perspective is using tools where the trouble
is apparent, such as ksh, rm, ls, et al. Perhaps the real
trouble is the file system allows inappropriate characters
in file names! How much nicer the world would have been
for Korn and others if they didn't have SO MUCH to worry
about when writing their shells. Mr Korn had it tough.
Twice. First with ksh88<->sh and then ksh93<->ksh88, so
to maintain compatibility is actually quite remarkable
achievement, but he has to maintain the baggage, too.

Reading your essay it's a wonder any shell programming is
done at all. But then, people solve problems within the
domains of their own influence, ie, I don't care about
the French locale (or any locale for that matter) because
I will never be writing a production oriented script that
will EVER need it. That's not being arrogant, it's just
a reckless waste of my employer's time.

--
David Thompson
Foster City, CA


Dan Mercer

unread,
Jun 25, 2003, 5:06:43 PM6/25/03
to

"Stephane CHAZELAS" <stephane...@yahoo.fr> wrote in message news:slrnbfiode.42.s...@pcchazelas.free.fr...

: Walt Fles wrote:
: > Korn Shell 93 ROCKS!
: > It is far superior from bash or bourne.
: [...]
:
: I see more and more often in this newsgroup enthusiastic posts about the
: ksh93 shell. I'd like to temper it a bit. I consider ksh and especially
: ksh93 one of the worst shell ever written, and especilly, its claim to
: be a good choice for a programming language is ridiculous. By no mean
: can it be compared to interpreted languages like perl/python/ruby/tcl.
:

DELETIA
:
: 1- Poor design.


:
: The problem is that it tried to keep some Bourne shell
: /compatibility/, not in the best way. ksh93 inherits from ksh88
: which inherits from Bourne shell. It kept the most annoying
: "features" of sh and brought new ones. Too bad that POSIX standard
: for sh was based on a great part of ksh88. Now, we encounter many of
: ksh design awkwardnesses in most shells

Since you don't mention which features, it's difficult to debate this point.
:
: 2- * is either '*' or a list of files


:
: echo *** title ***
: will output "*** title ***" only if there's no file in the current
: directory.

:

Yeah, but

echo "*** title ***"

won't have a problem.. So how is this a problem for any but the unitiated
or ignorant?

: for file in *


: will loop through files in the current directory. But you'll have a
: nasty effect if there's no file.

Not really. Not if you do it right:

for file in *
do
[[ -a $file ]] || continue
...
done


:
: Worse:


: rm file.[cC]
: removes any of a file.c or file.C file if they exist. But, if they
: don't, a file named "file.[cC]" might be unintentionnally removed.

But this is a shell feature, not a shell programming feature. Any way you
approach globbing will have trade offs.
:
: That makes globbing hard to use reliably and force you to quote


: everything in case it could be considered as a file pattern when you
: don't want it to. This is such an annoying feature that one could
: consider it as a bug (see zsh for a correct behavior).

zsh has different behavior.

:
: As an example http://www.research.att.com/~dgk/ksh/script/env (on


: David Korn's home page) contains "getopts '[-]' opt --???man".
: --???man is a wildcard and David forgot to quote it. So if there's a
: file named "--batman" in the current directory, his script will be
: broken.
:
: ksh93 introduced many new globbing operators. So, for each character
: you type, you have to be careful it's not a globbing operator.

ksh93 has extended globbing sequences. It's unlikely any would show
up as file names. However, is it really asking much to quote strings?

:
: So, to be sure, you should quote every word.

That's ridiculous. You should provide an example if you believe that to be true.

But you can't quote
: keywords. You have to perfectly know the syntax of ksh to be able to
: use it reliably (did you know "while" was a keyword while "break"
: was a builtin?).

Of course - it takes an optional argument (the number of loops to exit).
Admittedly, "break n" violates a lot of structured programming
tenets, but it has its uses.

It has that many corner cases that its almost
: impossible. Look at David Korn's himself ksh scripts on its home
: page, most contain numerous flaws even the shortest ones.

Again, a single example would be instructive.
:
: 3- $var is either a pattern or a list or a string or combination of


: those despite ksh93 has array type variables.
:
: ksh93 has arrays, you can do
:
: list=("file 1" "file 2")
: for file in "${list[@]}"; do
: something with "$file"
: done
:
: So, the old Bourne
: list="file 1,file 2" IFS=,
: set -f
: for file in $list; do
: ...
: done

Why do you neeed to "set -f"

:
: should no longer be necessary. But ksh decided to keep the bourne


: compatibility. Consequence is that you need to quote every *string
: type* variable so that it is not considered as a Bourne like list or
: a globbing pattern (or you must issue a "IFS=; set -f" at the
: beggining of the script).

again, I don't get your point. Can you show an example of how this
would be a problem?
:
: Each time you want to split a string, you have to disable filename
: generation (on by default).

Again, I need to see an example of something broken.
:
: This may also be considered as a bug (see zsh for a correct way).


:
: 4- cryptic syntax.
:
: copying two arrays is:
:
: set -A new_array -- "${old_array[@]}"
:
: compare with rc:
: new_array = $old_array

Yes, but in ksh $array and ${array[0]} are synonymous. This allows you
to do many things. Indeed, the standard method in ksh88 of not
having ENV set for scripts depended on this.
:
: or zsh:


: new_array=($old_array)
:
: read the (not fully documented) getopts builtin man page and laugh.
:
: no consistant variable expansion syntax: various non-intuitive

: operators of different shape. Hard to know whether/how they can be
: combined.

getopts using the ksh88 syntax is dead simple to use, especially
if you are used to the C version. The longname version is more complicated,
just as it is in C. If you know how to use one, you know how to use
the other. No one puts a gun to your head in either case.

:
: corner cases everywhere. word splitting was originally designed to


: make the shell user life easier in most cases. For an interactive
: use, you generally don't have to worry, it works. However, if you
: want to consider ksh as a programming language and use word
: splitting for text splitting, you have to know in details how it
: works. Check at
: www.opengroup.org/onlinepubs/007904975/utilities/xcu_chap02.html#tag_02_06_05
: and cry... ksh syntax is full of corner cases, for many variable
: expansion operators, there are various quoting/escaping
: mechanisms... Compare the "rc" man page and the "ksh93" man page.
:
: You can read and understand "rc" man page in less than one hour. You
: can be an efficient "rc" programmer and write acceptably reliable rc
: scripts in one day. Who can pretend he can write reliable ksh
: scripts?

Gee, I did it for 11 years. Lots of dtksh scripts too, used by hundreds of users
with no defects reported.

:
: 5- command substitution removes too many NLs


:
: Usual commands display the value they have to display followed by a
: newline character. Because they display them on a text line and a
: text line is terminated by a NL character on Unix.
:
: for instance, "basename a/b" outputs "b\n"
:
: To store the value returned by that command in a variable, you must
: remove that trailing NL. That's what command substitution does,
: except that instead of removing the trailing NL, it removes *every*
: trailing NL (even those that are part of the value returned by the
: command).

This is documented. You have a choice - every trailing newline or none.
Having every trailing newline would create more problems than having none.

:
: So, you'd think


:
: print -r -- "$(cmd)"
: outputs the same as
: cmd

Not if you read the man page.

:
: It doesn't, except when the value returned by the command doesn't


: end with a newline character.
:
: To work around this, you have to do:
: var=$(cmd; echo .)
: var=${var%?} var=${var%?}

I wouldn't know. In 11 years it never came up.

:
: 6- danger of using a shell both as a shell and as a programming


: language.
:
: Historically, you made shell "scripts" not programs, i.e. you put a
: sequence of command in a file so that you don't have to type it each
: time.
:
: But when putting the sequence of commands you'd have typed in a
: file, you forget to put another very important thing in it: your
: brain. When you use the shell interactively, there's processing done
: by the shell and the command it runs, but also by your mind.
:
: After each command you type, you observe the result and take the
: decision to run or not this or that next command (or even to
: interrupt a command when it is going to behave incorrectly).
:
: When in a script, who will check the command ran correctly?
:
: When you write a C program, you always do things like this:
:
: if (chdir(variable) < 0) {
: perror("chdir");
: exit(1);
: }
:
: In a shell, most forget to do
: cd -- "$var" || exit
: because they are used to only typing
: cd $var
: at the prompt and look at the result.

You can't blame bad programming technique on anything but bad
programmers. "Look at this stupid gun. I put it to my head and pull the trigger
and ..."

You can't both argue that ksh is not a programming language and then blame it
for people using it in a manner not appropriate for a programming language.

:
: Moreover, commands are often made to be run interactively. The


: information on failure is a text intended for a human on standard
: error. So, generally, a script will be unable to parse that error
: message to take appropriate action.
:
: That's one of the most important reasons why a shell shouldn't be
: seen as a programming language.

Oh gee, and there's no way we could capture stderr!

:
: 7- read/print do extra processing by default


:
: from a programming language, you'd expect ways to read data into a
: variable, and output the content of a variable.
:
: The usual commands to do this (read, print, echo) fail to do it
: reliably when not passed specific options. Default behavior of read
: or print are to perform extra processing on the value read or
: written.
:
: If you want to read a line of input, it's
: IFS= read -r variable
: If you want to write the content of a variable, it's
:
: print -r -- "$variable"

And yet we still have echo for the lazy!

: or


: echo "${variable//\\/\\\\}"
: (provided that for some obscur reason, for example the content of
: the PATH variable, echo doesn't recognize options)

echo is a shell builtin. What possible effect could the PATH variable have on it?

:
: 8- "--" necessary


:
: In shell language, there are few statements, most of the processing
: is performed by commands (builtin or not). Commands take operators
: and operands as in every language except that in shell operands and
: operators are both arguments. The way you distinguish them can be
: there position on the command line, or their content. For exemple,
: an argument located after the command name and starting with a dash
: will be an option (an operator lets say) while one not starting with
: a dash and placed after an option that expects an argument will be
: an operand (data).
:
: Ok, but what happens if the data starts with a dash. What if I want
: to go in the "-P" directory?
:
: cd -P # and I silently go in my home directory instead
: # of the -P one (because -P is taken as an option to cd).

What if I want to remove a file name -P? We see that one often enough. Again,
this is a tradeoff with using getopts and the inability of software to guess what
you want.

:
: If I were at shell prompt, I would have realized it would cause a


: problem, or at least, I would have realized afterwards that I was
: not in the "-P" directory (for example because my prompt displays
: the current working directory). So I would have used cd ./-P
: instead.
:
: But, in a script, if I put
: cd "$1" && rm -f *
: where "$1" is a user provided directory. Suppose "$1" is "-P", and
: the first file in your home directory is named "-r". This command
: resolves to:
:
: cd -P && rm -f -r every file and dir in your home directory

:
: For most commands, there's a work around: the "--" argument to
: separate options from arguments. So the command line above is best
: written:
:
: cd -- "$1" && rm -f -- *
:
: The problem is that some commands don't accept that syntax, and it
: can't be applied to some others because they have not the shape:
: command [options] arguments

Now you are just getting silly.

:
: Examples are find, test ([), expr.

Again, is this really a problem? Guess what, you can't name a script
"while" or "test" or "for" etc. either.

:
: Work around is to use:


: #! /usr/local/bin/ksh93 -
:
: 12- Documentation.
:
: ksh93 documentation is disseminated. The man page doesn't describe
: half of the behavior. To know about a builtin, you have to run ksh93
: and issue the (undocumented):

It certainly is not undocumented. Under "BUILTIN COMMANDS" it clearly
states to enter "cmd --man" to get a man page for the command.
:
: builtin --man


: or
: builtin --help
: or
: builtin --html
: (yes all the documentation is in the binary ksh93 executable! This
: certainly goes against most system documentation policy)

Not against mine. I've always included documentation with everything
I've written.
:
: That doesn't work with every builtin (echo, :),

Of course not. Only with commands that already take arguments.
Otherwise you would not be backwards compatible.

and for keywords

keywords don't take arguments. They are part of the syntax.

: (for, while...). At least, even if it's arguable to put the


: documentation in the code, bash chose a dedicated builtin for that
: (help) and has a full man/info/html page.

different strokes for different folks
:
: 13- Poor interactive shell


:
: shell vocation is to be used at prompt. ksh93 is one of the most
: poorly featured one: no programmed (or even programmable)
: completion, no incremental search, poor history facilities, poor
: extended key handling, poor prompt facilities

No, different prompt facilities. You just don't know how to use them, appparently.

, no multiline command
: editing,

Of course there is. You can even choose the editor.

no spelling correction, no rc file except via the dumb ENV

What's so dumb about it? At least ksh's policy doesn't violate
structured programming tenets.

: variable processing (shared with other shells, so shouldn't be used,

: }
:
cool

: statement works and is not documented. Problem with undocumented


: features is that you can use them but you are not guaranteed they
: will be in the next version.
:
: 15- approximate syntax permitted:
:
: unmatched quotes permitted in some cases:
: a=`echo "a`
: b="`echo b"
: c="`echo \"" # $c empty
: ...
:
: fuzzy syntax.
:
: { (( 0 )) }
: { ( false ) }
: are allowed
:
: { false }
: not ("}" is a keyword so must start a new command, but still is
: allowed after ")").
:
:
: 16- arithmetic expansion that depends on locale
:
: #! /usr/local/bin/ksh93 -
: typeset -F pi=3.14159265359
: echo "cos(pi/2) is $(( cos(pi/2) ))"
:
: when run in a french locale gives:
:
: ksh93: .[2]: typeset: 3.14159265359: arithmetic syntax error
: because in french, the decimal point is a comma.

Good to know.

:
: 17- "export var" when var is unset doesn't put "var" in the environment.

And it shouldn't. It only marks it for export. "export var=" will put it in the


environment.
:
: 18- 010 and 08 and 008 are 8... sometimes
:
: $ typeset -Z3 i=008 j=010
: $ echo $i $j
: 008 010
: $ typeset -i i j
: $ echo $i $j
: 8 10
: $ typeset -i i=008 j=010
: $ echo $i $j
: 8 8
: $ typeset -Z3 i j
: $ echo $i $j
: 008 008
:
: This is really annoying when dealing with dates:

Yeah, I don't like this either. This was a late change to meet POSIX standards,
I believe.
:
: 19- arrays start at index 0


:
: Bourne shell had one array (one global and one per function
: actually): the positional parameters ($@). You could fill it with
:
: set -- "value 1" "value 2"
:
: With ksh93, you fill an array with
:
: set -A array -- "value 1" "value 2"
:
: With Bourne shell, you put "value 1" in element of indice 1, with ksh
: arrays, you start with 0 ($1 would be ${@[0]})

Oh, c'mon - that's really picky.

:
: 20- two (sometime compatible) ways to access array elements.


:
: ${array[@]:3:1} and ${array[3]} are the same
: except in the (not so usual) case where element indices are not
: contiguous or don't start at 0
:
: To obtain a slice of an array, you can do
: slice=("${array[@]:first:number}")
:
: But again, "first" is not an array index, it's the position number in
: the list.
:
: To obtain the slice for index 3 to index 7, you have to do:
: slice=()
: for i in "${!array[@]}"; do
: (( i >= 3 && i <= 7 )) && slice=("${slice[@]}" "${array[i]}")
: done
:
: Compare with "es":
:
: slice = $array(3...7)
: "es" guarantees indices to be contiguous and start at 1.
:
: or zsh:
:
: slice=($array[3,7])

So use them instead.

:
: 21- conflict between ${var:-default} and ${var: -1}


: ${var:0} is the first char in "$var", i=-1, ${var:i} is the last
: char in "$var", but ${var:-1} is $var or "1" if it's empty (as in
: Bourne shell). Why didn't ksh use a construct like ${var[i..j]} to
: be consistant with array subscripting, instead of that confusing
: ${var:offset:length}?
:
: note that
: var="101 reason to avoid ksh"
: echo ${var:#10}
: echo ${var:2#10}
: give the same result (with ksh88 and ksh93o only).
:
: 22- confusing versionning policy
: The 93 is only the year of the first release of that branch of ksh.
: A script working with one ksh93, will not necessarily work with
: another ksh93, you've got to know the release letter (latest as of
: this writing is "o")
:
: 23- ksh93 is not open source in the OSI meaning of it
:
: 24- exit status policy different from any other shell's
:
: $? contains 256 + signum when a command was killed instead of 128 +
: signum in every other shell.

Every other shell got it wrong?

:
: In conclusion, it might be possible for one knowing in details the ins


: and outs of ksh and the common traps of shell programming to write
: reliable ksh scripts. But, if you apply all the work arounds I showed
: above, I guess you see how illegible and unmaintainable a /correct/
: script would be.

And somehow this flies in the face of the experiences of thousands
of ksh'ers.

:
: ksh93 comes with features that could appear useful for a programming


: language (pre-compilation, inline documentation, TCP socket support,
: disciplines (I've yet to see what it can be useful to)

disciplines are essential to the use of the alarm command, for instance, and
to dtksh programming.

, kind of regular
: expressions, math library function...), but they are brought over a
: really broken basis. You don't build a spaceship on top of a bicycle
: frame!

But the Wright bros built an airplane that way. Look, you may not
want to fly an airplane on a ksh script, but it's damn useful in a hundred other
ways.

:
: Thanks for reading, feel free to argue on all this. Of course, I exposed


: only the arguments *against* writing shell scripts. There are toward
: writing scripts in some circumstances, but generally not with the ksh93
: shell.
:
: --
: Stéphane

Then don't.


Dan Mercer
dme...@mn.rr.com


Stephane CHAZELAS

unread,
Jun 26, 2003, 5:29:41 AM6/26/03
to
Dan Mercer wrote:
[...]

>: 2- * is either '*' or a list of files
>:
>: echo *** title ***
>: will output "*** title ***" only if there's no file in the current
>: directory.
>:
>
> Yeah, but
>
> echo "*** title ***"
>
> won't have a problem.. So how is this a problem for any but the unitiated
> or ignorant?

Are you saying that David Korn is an unitiated or ignorant ksh
programmer? I wouldn't have dared ;).

He wrote:
getopts '[-]' opt --???man

quoted the first, not the second pattern, didn't quote "getopts"
(I guess he knew it was not a pattern, but to be sure, it
wouldn't have harmed to write:

'getopts' '[-]' 'opt' '--???man'
)

>: for file in *
>: will loop through files in the current directory. But you'll have a
>: nasty effect if there's no file.
>
> Not really. Not if you do it right:
>
> for file in *
> do
> [[ -a $file ]] || continue
> ...
> done

You tell it! So the right way to loop through the files in the
current directory is that? I don't find it much intuitive nor
legible.

Note that in src/cmd/ksh93/OBSOLETE in ksh93 source
distribution, one can read:

3. The newtest ([[ ... ]]) operator -a file is obsolete.
Use -e instead.

Although I agree it was more accurate. It doesn't check for
file existance, but for file accessibility.

So your loop loops through accessible files (which I agree
doesn't make much difference and even is preferable).

In zsh, by default, in

for file in *; do

...
done

if there's no file, you get an error message, and there's no
pass in the loop.

If you consider that it's a normal thing when there aren't files,
you write:

for file in *(N); do
...
done

>:
>: Worse:
>: rm file.[cC]
>: removes any of a file.c or file.C file if they exist. But, if they
>: don't, a file named "file.[cC]" might be unintentionnally removed.
>
> But this is a shell feature, not a shell programming feature. Any way you
> approach globbing will have trade offs.

In zsh, if I run this and there's no matching file, rm is not
run, I get an error message, so no way I can delete a file
unintentionnally..

[...]


>: As an example http://www.research.att.com/~dgk/ksh/script/env (on
>: David Korn's home page) contains "getopts '[-]' opt --???man".
>: --???man is a wildcard and David forgot to quote it. So if there's a
>: file named "--batman" in the current directory, his script will be
>: broken.
>:
>: ksh93 introduced many new globbing operators. So, for each character
>: you type, you have to be careful it's not a globbing operator.
>
> ksh93 has extended globbing sequences. It's unlikely any would show
> up as file names. However, is it really asking much to quote strings?

The "unlikely" thing is a bit unpleasant to the ear of a
programmer, unless you want to do approximate programming.

>
>:
>: So, to be sure, you should quote every word.
>
> That's ridiculous. You should provide an example if you believe that to be true.

I provided one (courtesy of David Korn).

In a real programming language, you have litteral strings,
litteral integer, keywords, variable references, function calls,
and a way to differenciate each (strings inside quotes, function
calls followed by (...)...). You can't take a function for a
string an integer for a keyword.

In shell, that's not the case. Everything is more or less mixed.
There's no clear boundary anywhere.

You may introduce one, by for example considering that a non
quoted word is either a keyword or a pattern, while a quoted one
is a string. So you could write things like:

for 'file' in *; do

'[' '-e' "$file" ']' || 'continue'
...
done

That would made syntax a little more consistant, help to avoid
problems in corner cases, but would make it even more illegible.

>
> But you can't quote
>: keywords. You have to perfectly know the syntax of ksh to be able to
>: use it reliably (did you know "while" was a keyword while "break"
>: was a builtin?).
>
> Of course - it takes an optional argument (the number of loops to exit).
> Admittedly, "break n" violates a lot of structured programming
> tenets, but it has its uses.

"time", "!" take arguments somehow, they are keywords

> It has that many corner cases that its almost
>: impossible. Look at David Korn's himself ksh scripts on its home
>: page, most contain numerous flaws even the shortest ones.
>
> Again, a single example would be instructive.

Other examples from Mr Korn. Again in its "env" script.
To clear the environment "typeset +x $(typeset +x)"
It only clears shell variable like environment variables, and
not the "_" one (well it's still exported to the next command
run).

Another one in the same file:

command unset $OPTARG 2> /dev/null

If the user thinks this env script is like the real env command,
he might want to unset the "*" variable.

In ksh, an unquoted variable can be considered as a list of
files (unless maybe if you know what's in it).

>:
>: 3- $var is either a pattern or a list or a string or combination of
>: those despite ksh93 has array type variables.
>:
>: ksh93 has arrays, you can do
>:
>: list=("file 1" "file 2")
>: for file in "${list[@]}"; do
>: something with "$file"
>: done
>:
>: So, the old Bourne
>: list="file 1,file 2" IFS=,
>: set -f
>: for file in $list; do
>: ...
>: done
>
> Why do you neeed to "set -f"

Because I consider $list as a list of strings, not as a list of
patterns. In that case, if I change $list to:

list="file [1],file [2]"
I really mean the file named "file [1]" and I expect my script
to keep running correctly.

On the other hand, if I wanted to consider the list as a list of
patterns, I could have ommitted the "set -f". But chances are I
would have prefered to do the filename generation at the
assignment level, not at the variable expansion one:

list=( "file "[1] "file [2]" *".txt" ) # in ksh

set -- file "[1] "file [2]" *".txt"
IFS=","
list="$*" # in sh

>:
>: should no longer be necessary. But ksh decided to keep the bourne
>: compatibility. Consequence is that you need to quote every *string
>: type* variable so that it is not considered as a Bourne like list or
>: a globbing pattern (or you must issue a "IFS=; set -f" at the
>: beggining of the script).
>
> again, I don't get your point. Can you show an example of how this
> would be a problem?

See the OPTARG example above. And half the scripts posted in
this newsgroup. In 95% of the time, people forget to quote
variable references.

>: Each time you want to split a string, you have to disable filename
>: generation (on by default).
>
> Again, I need to see an example of something broken.

For example, one of your posts:
Message-ID: <Cm6Fa.2548$fe.1...@twister.rdc-kc.rr.com>

function split {
# split Arrayname delimiter values
typeset _vname=${1:?} _IFS=${2:?}
shift 2
set -A $vname -- $*
}

Well, I guess you meant vname and IFS instead of _vname and _IFS=.

What happens if I do:

'split' 'array' ',' '*,+,/,-'
?

Or

'split' 'array_name' '_' '1_2_3_4'


[...]


>: 4- cryptic syntax.
>:
>: copying two arrays is:
>:
>: set -A new_array -- "${old_array[@]}"
>:
>: compare with rc:
>: new_array = $old_array
>
> Yes, but in ksh $array and ${array[0]} are synonymous. This allows you
> to do many things. Indeed, the standard method in ksh88 of not
> having ENV set for scripts depended on this.

Yes $var is either a string, a list of pattern, the 0th element of an array...
That's not what I call a consistant typing. Compare with rc:

Default (and only) variable type in rc is array:
var = 'string'
is actually a shortcut for
var = ('string')

It's the same in ksh93 but who knows it?

in rc, there's no word splitting of variable expansion, when you do

command $var

it's the same as ksh's:
command "${var[@]}"

In ksh, "command $var" passes the element of indice 0 of $var on
which is performed filename generation, tilde expansion and
word splitting.

zsh arrays and string variables are of different types.

var1="string" # defines a "scalar" type variable
var2=("string") # defines a "array" type variable

command $var1
# passes *one* "scalar" argument to command

command $var2
# passes as many arguments as there are elements in the array to
# command.

Don't you find it a more intuitive and consistant behavior?

[...]


> Gee, I did it for 11 years. Lots of dtksh scripts too, used by hundreds of users
> with no defects reported.

I'm sure *you* can write correct scripts. But admit ksh93
doesn't "ROCK" (as it was what I was replying to) and shouldn't
be advised to a beginner and certainly not for "programming".

>: 5- command substitution removes too many NLs

[...]


> This is documented. You have a choice - every trailing newline or none.
> Having every trailing newline would create more problems than having none.

So, you agree?

>: So, you'd think
>:
>: print -r -- "$(cmd)"
>: outputs the same as
>: cmd
>
> Not if you read the man page.

But "yes", if you'd expect ksh programming to be a bit intuitive
and consistant.

>: It doesn't, except when the value returned by the command doesn't
>: end with a newline character.
>:
>: To work around this, you have to do:
>: var=$(cmd; echo .)
>: var=${var%?} var=${var%?}
>
> I wouldn't know. In 11 years it never came up.

That's again about the "unlikely". As long as you don't write
software for powerplants or CGIs, you may not care about
writing approximate software that work most of the time.

I wouldn't write powerplant software in perl either. But many
write CGI scripts in perl, perl being a programming language
(with its flaws too, but far less than in ksh).

>: 6- danger of using a shell both as a shell and as a programming
>: language.

[...]


>: In a shell, most forget to do
>: cd -- "$var" || exit
>: because they are used to only typing
>: cd $var
>: at the prompt and look at the result.
>
> You can't blame bad programming technique on anything but bad
> programmers. "Look at this stupid gun. I put it to my head and pull the trigger
> and ..."
>
> You can't both argue that ksh is not a programming language and then blame it
> for people using it in a manner not appropriate for a programming language.

Yes, but you and David Korn and I and every one fall in that
trap.

>: Moreover, commands are often made to be run interactively. The
>: information on failure is a text intended for a human on standard
>: error. So, generally, a script will be unable to parse that error
>: message to take appropriate action.
>:
>: That's one of the most important reasons why a shell shouldn't be
>: seen as a programming language.
>
> Oh gee, and there's no way we could capture stderr!

Yes, uneasily, making scripts even more illegible, you'd have to
cope with message localization, write a complex parser for every
error. In other programming languages, library functions return
a errno suitable for analysis by an /automate/ (and *then* you
display an error message to the human user). Shell library
functions are commands whose output is directly intended to a
human user, in a narrower extent to an automate (the exit status
is often limited to success/error).

[...]


>: echo "${variable//\\/\\\\}"
>: (provided that for some obscur reason, for example the content of
>: the PATH variable, echo doesn't recognize options)
>
> echo is a shell builtin. What possible effect could the PATH variable have on it?


src/cmd/ksh93/bltins/print.c:
int B_echo(int argc, char *argv[],void *extra)
{
[...]
if(!bsd_univ)
return(b_print(0,argv,&prdata));
[...]
if(argv[1] && strcmp(argv[1],"-n")==0)
prdata.echon = 1;


Look at src/lib/libast/port/astconf.c
for how bsd_univ is determined

~$ PATH=/usr/ucb:/bin /usr/local/bin/ksh93 -c 'echo -n'
~$ PATH=/bin:/usr/ucb /usr/local/bin/ksh93 -c 'echo -n'
-n
~$

[...]


> What if I want to remove a file name -P? We see that one often enough. Again,
> this is a tradeoff with using getopts and the inability of software to guess what
> you want.

Yes, that inability is proper to shell programming. In every
real language, there's no problem with

unlink("-P")
chdir("-P")

[...]


>: cd -- "$1" && rm -f -- *
>:
>: The problem is that some commands don't accept that syntax, and it
>: can't be applied to some others because they have not the shape:
>: command [options] arguments
>
> Now you are just getting silly.

Thanks, why? Because I try to imagine ways how to do programming
with shells? I think I have to agree, that's a bit silly.

[...]


>: 11- behavior of a script depends on its name!
>:
>: cd /tmp
>: PATH=$PATH:
>: echo '#! /usr/local/bin/ksh93' > script.ksh
>: chmod 755 script.ksh
>: ln -s script.ksh ./--man
>: ln -s script.ksh ./-i
>:
>: "script.ksh", "-i" and "--man" are supposed to be the same script.
>: However, the first one does nothing, the second runs an interactive
>: shell, and the third one displays a short ksh93 man page!
>
> Again, is this really a problem?

Not really, except in the case of setuid scripts (check the
unix-faq). And you'll have problem with perl or python too,
that's more a shebang issue than a shell issue.

> Guess what, you can't name a script
> "while" or "test" or "for" etc. either.

Sure I can, why couldn't I?

That's even another arguments toward always quoting every
argument.

If I write:

'while' 'arg1' 'arg2'
I kind of force the typing. I'm sure 'while' is taken as a
command argv[0]. Maybe in ksh93p, there will be a new "perhaps"
keyword, so you'll be happy that your scripts correctly written
as:

function 'perhaps' {
'typeset' 'IFS= '
'print' '-r' '--' "Maybe I should $*"
}
'perhaps' 'try another shell'

will continue to work.

[...]


>: 12- Documentation.
>:
>: ksh93 documentation is disseminated. The man page doesn't describe
>: half of the behavior. To know about a builtin, you have to run ksh93
>: and issue the (undocumented):
>
> It certainly is not undocumented. Under "BUILTIN COMMANDS" it clearly
> states to enter "cmd --man" to get a man page for the command.

Yes --man is. I missed that. "--api", "--author", "--html",
"--about", "--nroff", "--long", "--short", "--help", "--keys"...
are not.


>:
>: builtin --man
>: or
>: builtin --help
>: or
>: builtin --html
>: (yes all the documentation is in the binary ksh93 executable! This
>: certainly goes against most system documentation policy)
>
> Not against mine. I've always included documentation with everything
> I've written.

I generally include it in a man page. To learn about a software,
I type "man <software>", not "<software> --man 2>&1 | ${PAGER-more}"

>:
>: That doesn't work with every builtin (echo, :),
>
> Of course not. Only with commands that already take arguments.
> Otherwise you would not be backwards compatible.

That's why I say, that was a silly way to do it. and that bash's
help builtin was better.

> and for keywords
>
> keywords don't take arguments. They are part of the syntax.

Yes, same as above. In bash, you can do "help for".

>
>: (for, while...). At least, even if it's arguable to put the
>: documentation in the code, bash chose a dedicated builtin for that
>: (help) and has a full man/info/html page.
> different strokes for different folks

Yes, the poster I replied to said "ksh93 was far superior to
bash". Not on this.

>: 13- Poor interactive shell
>:
>: shell vocation is to be used at prompt. ksh93 is one of the most
>: poorly featured one: no programmed (or even programmable)
>: completion, no incremental search, poor history facilities, poor
>: extended key handling, poor prompt facilities
>
> No, different prompt facilities. You just don't know how to use them, appparently.

No, I didn't even try. I had just to compare zsh's prompt
expansion, prompt themes with ksh's.

>
> , no multiline command
>: editing,
>
> Of course there is. You can even choose the editor.

No, I meant a shell command line editor; you can't search the
shell history when you've started vi, for instance.

> no spelling correction, no rc file except via the dumb ENV
>
> What's so dumb about it?

Many reasons. First the name. Who can imagine a less specific
name than "ENV" for an environment variable. Every program could
have used this name for a variable used to set up its
environment. I would have expected at least KSH_ENV or
KSH93_ENV.

Its content is read for every shell (interactive or script
interpreters). By "rc" file, I meant a shell customization file.
If, at prompt, I like the noclobber option, and put it in the
ENV file, I'll break most scripts.

This var is shared for too different purposes (more if you
consider this variable is read by every POSIX compliant shell),
why not having used two separate mechanisms (look zsh and its
zshenv and zshrc files).

That's why you see ugly things like

export INTERACTIVE_ENV="$HOME/.kshrc"
export ENV='${INTERACTIVE_ENV[(Z$-=0)+(Z=1)-Z${-%%*i*}]}'

(which doesn't allow for a ENV for non-interactive shells).


> At least ksh's policy doesn't violate
> structured programming tenets.

How can you speak of "structured" which such a fuzzy syntax...

[...]


>: for i in 1 2
>: {
>: print -r -- "$i"
>: }
>:
> cool

Isn't it? It's in every Bourne like shell.

[...]


>: 16- arithmetic expansion that depends on locale
>:
>: #! /usr/local/bin/ksh93 -
>: typeset -F pi=3.14159265359
>: echo "cos(pi/2) is $(( cos(pi/2) ))"
>:
>: when run in a french locale gives:
>:
>: ksh93: .[2]: typeset: 3.14159265359: arithmetic syntax error
>: because in french, the decimal point is a comma.
>
> Good to know.

And I didn't speak of all the issues related to LC_COLLATE, LC_CTIME...
In other programming languages, you have to explicitely activate
localization. In shells, you have to disable it.

>: 17- "export var" when var is unset doesn't put "var" in the environment.
>
> And it shouldn't. It only marks it for export. "export var=" will put it in the
> environment.

Yes, you're right even if that depends on how you interpret POSIX:

The shell shall give the export attribute to the variables
corresponding to the specified names, which shall cause them
to be in the environment of subsequently executed commands.

Most modern shells seem to agree with you.

[...]


>: 19- arrays start at index 0

[...]


> Oh, c'mon - that's really picky.

But that's annoying. That's a small one of ksh's many
inconsistancies.

[...]
>: Compare with "es":
[..]
>: or zsh:
[...]
> So use them instead.

Of course I do. My point here is to say that no, we can't say
"KSH93 ROCKS", use zsh instead for interactive shell, and a
programming language for programming stuff, ksh93 is good at
neither one.

[...]


>: 24- exit status policy different from any other shell's
>:
>: $? contains 256 + signum when a command was killed instead of 128 +
>: signum in every other shell.
>
> Every other shell got it wrong?

No. I prefer the ksh93 way, but it breaks compatibility

[...]


> , kind of regular
>: expressions, math library function...), but they are brought over a
>: really broken basis. You don't build a spaceship on top of a bicycle
>: frame!
>
> But the Wright bros built an airplane that way. Look, you may not
> want to fly an airplane on a ksh script, but it's damn useful in a hundred other
> ways.

Yes, in response to "KSH93 ROCKS", I say no,
It's a really poor bicycle, use zsh instead.
It's a really broken airplane, use python instead.

--
Stéphane

Stephane CHAZELAS

unread,
Jun 26, 2003, 5:29:42 AM6/26/03
to
David Thompson wrote:
[...]

> Shell programming is what it is, baggage and all. It is quick
> and useful and has grown with the times. IMHO, ksh has done an
> admirable job in an unforgiving world where the successful
> programs can only grow in ways that maintain backwards
> compatibility with their installed bases.

Note that it didn't maintain complete compatibility with Bourne
shell. There are compatibilities it could have dropped to help
having a simpler and more consistant shell (I encourage everyone
to read "rc"'s (or esh out of curiosity) man page to see what
else a shell could have been if we hadn't have to stick with
Bourne compatibility. See also how zsh managed to keep Bourne
compatibility (to a less extent than ksh) while being still
usable.

> Of course, my perspective is using tools where the trouble
> is apparent, such as ksh, rm, ls, et al. Perhaps the real
> trouble is the file system allows inappropriate characters
> in file names!

ksh93 claims to be a programming language not only for file
manipulation. Filenames are not the only problem.

> Reading your essay it's a wonder any shell programming is
> done at all.

Many scripts I can see and saw are broken. I guess you also had
to debug shell scripts that worked a for a while, and then
stopped working because of a silly side effect.

> I don't care about the French locale (or any locale for that
> matter) because I will never be writing a production oriented
> script that will EVER need it. That's not being arrogant,
> it's just a reckless waste of my employer's time.

But you have to beware that if you write a shell script that
makes use of floating point arithmetic, a french guy will not be
able to use it.

As long as one write shell script for his own use, it's allright
for me ;)

--
Stéphane

Dan Mercer

unread,
Jun 26, 2003, 12:47:54 PM6/26/03
to

"Stephane CHAZELAS" <stephane...@yahoo.fr> wrote in message news:slrnbfle8k.3v.s...@pcchazelas.free.fr...

: Dan Mercer wrote:
: [...]
: >: 2- * is either '*' or a list of files
: >:
: >: echo *** title ***
: >: will output "*** title ***" only if there's no file in the current
: >: directory.
: >:
: >
: > Yeah, but
: >
: > echo "*** title ***"
: >
: > won't have a problem.. So how is this a problem for any but the unitiated
: > or ignorant?
:
: Are you saying that David Korn is an unitiated or ignorant ksh
: programmer? I wouldn't have dared ;).
:
: He wrote:
: getopts '[-]' opt --???man

In a man page, though my man page says "--??man" and "--man" works.
Again, this is a problem with any globbing. Also note that getopts --man
won't be called in a script.

:
: quoted the first, not the second pattern, didn't quote "getopts"


: (I guess he knew it was not a pattern, but to be sure, it
: wouldn't have harmed to write:
:
: 'getopts' '[-]' 'opt' '--???man'
: )
:
: >: for file in *
: >: will loop through files in the current directory. But you'll have a
: >: nasty effect if there's no file.
: >
: > Not really. Not if you do it right:
: >
: > for file in *
: > do
: > [[ -a $file ]] || continue
: > ...
: > done
:
: You tell it! So the right way to loop through the files in the
: current directory is that? I don't find it much intuitive nor
: legible.

It's the way I've done it for 12 years. And certainly it's been mentioned
in this group a hundred times (at least 50 by me)

:
: Note that in src/cmd/ksh93/OBSOLETE in ksh93 source


: distribution, one can read:
:
: 3. The newtest ([[ ... ]]) operator -a file is obsolete.
: Use -e instead.

Yeah, I can never keep straight those two and I was too lazy to look it up.

:
: Although I agree it was more accurate. It doesn't check for


: file existance, but for file accessibility.

No, it tests for existance. It returns true even if the file has
no permission bits.

:
: So your loop loops through accessible files (which I agree


: doesn't make much difference and even is preferable).
:
: In zsh, by default, in
:
: for file in *; do
: ...
: done
:
: if there's no file, you get an error message, and there's no
: pass in the loop.
:
: If you consider that it's a normal thing when there aren't files,
: you write:
:
: for file in *(N); do
: ...
: done
:

Again, this is not a major problem and one easily dealt with, as are all error
conditions.

: >:
: >: Worse:


: >: rm file.[cC]
: >: removes any of a file.c or file.C file if they exist. But, if they
: >: don't, a file named "file.[cC]" might be unintentionnally removed.
: >
: > But this is a shell feature, not a shell programming feature. Any way you
: > approach globbing will have trade offs.
:
: In zsh, if I run this and there's no matching file, rm is not
: run, I get an error message, so no way I can delete a file
: unintentionnally..
:
: [...]
: >: As an example http://www.research.att.com/~dgk/ksh/script/env (on
: >: David Korn's home page) contains "getopts '[-]' opt --???man".
: >: --???man is a wildcard and David forgot to quote it. So if there's a
: >: file named "--batman" in the current directory, his script will be
: >: broken.
: >:
: >: ksh93 introduced many new globbing operators. So, for each character
: >: you type, you have to be careful it's not a globbing operator.
: >
: > ksh93 has extended globbing sequences. It's unlikely any would show
: > up as file names. However, is it really asking much to quote strings?
:
: The "unlikely" thing is a bit unpleasant to the ear of a
: programmer, unless you want to do approximate programming.
:
: >
: >:
: >: So, to be sure, you should quote every word.
: >
: > That's ridiculous. You should provide an example if you believe that to be true.
:
: I provided one (courtesy of David Korn).

You provided one obscure example that does not occur in scripts.
Show an example that might occur in a script.

:
: In a real programming language, you have litteral strings,


: litteral integer, keywords, variable references, function calls,
: and a way to differenciate each (strings inside quotes, function
: calls followed by (...)...). You can't take a function for a
: string an integer for a keyword.
:
: In shell, that's not the case. Everything is more or less mixed.
: There's no clear boundary anywhere.
:
: You may introduce one, by for example considering that a non
: quoted word is either a keyword or a pattern, while a quoted one
: is a string. So you could write things like:
:
: for 'file' in *; do
: '[' '-e' "$file" ']' || 'continue'
: ...
: done
:
: That would made syntax a little more consistant, help to avoid
: problems in corner cases, but would make it even more illegible.
:
: >
: > But you can't quote
: >: keywords. You have to perfectly know the syntax of ksh to be able to
: >: use it reliably (did you know "while" was a keyword while "break"
: >: was a builtin?).
: >
: > Of course - it takes an optional argument (the number of loops to exit).
: > Admittedly, "break n" violates a lot of structured programming
: > tenets, but it has its uses.
:
: "time", "!" take arguments somehow, they are keywords

No, "time" and "!" do not take arguments, any more than "for" or "while"
do. "time" runs the pipeline following it and displays the timing for it. If it were
a builtin, it would only run the first sequence in the pipeline. The same thing goes for
! - if it were not a keyword, it would only reverse the truth of the first segment
of a pipeline, not the whole pipeline.

:
: > It has that many corner cases that its almost


: >: impossible. Look at David Korn's himself ksh scripts on its home
: >: page, most contain numerous flaws even the shortest ones.
: >
: > Again, a single example would be instructive.
:
: Other examples from Mr Korn. Again in its "env" script.
: To clear the environment "typeset +x $(typeset +x)"
: It only clears shell variable like environment variables, and
: not the "_" one (well it's still exported to the next command
: run).

No, you are wrong on this. The sequence above clears the export
flag. But "$_" is one of the inherent variables, like "$!" "$$" "$PPID"
in every shell. It is automatically marked for export (why, I don't know).

So again, this is a misunderstanding on your part, not a failure on Korn's.

:
: Another one in the same file:


:
: command unset $OPTARG 2> /dev/null

:

Korn's example are just that - quick and dirty examples, not full
fledged production code. The example file you give even has a commented
out line of code. Since the globbing chars do not form legitimate
variable names, it's unlikely you would be trying to unset a variable
with that name. The example file demonstrates two things - how
to use the long options of getopts and how command can be used
to prevent premature and unexpected termination of a script.

if you

unset 123 2>/dev/null

in a script, it exits immediately. If you preface the statement with
command, it does not.


:
: In ksh, an unquoted variable can be considered as a list of

That's sloppiness or again, just sample code. Again, I think you are being
overly picky. Certainly from the number of ksh users you might have to
suppose that they are not running into these problems. I certainly never have.
:
: >: Each time you want to split a string, you have to disable filename


: >: generation (on by default).
: >
: > Again, I need to see an example of something broken.
:
: For example, one of your posts:
: Message-ID: <Cm6Fa.2548$fe.1...@twister.rdc-kc.rr.com>
:
: function split {
: # split Arrayname delimiter values
: typeset _vname=${1:?} _IFS=${2:?}
: shift 2
: set -A $vname -- $*
: }
:
: Well, I guess you meant vname and IFS instead of _vname and _IFS=.
:
: What happens if I do:
:
: 'split' 'array' ',' '*,+,/,-'
: ?
:
: Or
:
: 'split' 'array_name' '_' '1_2_3_4'

:

So you change the above to:

function split {
set -f


# split Arrayname delimiter values

typeset _vname=${1:?} IFS=${2:$IFS}
shift 2
set -A $_vname -- $*
}

There was more than one typo in that. Note that doing "set -f"
in a function only turns off globbing in the function.
One of the great things about ksh is the FPATH variable which
allows you to declare directories of functions.

The respondent wanted to split something like a,b,c,def so I typed
a hasty response to point her in the right direction. The actual split
function I employed at work is far longer and more bullet proof.
:
: [...]


: >: 4- cryptic syntax.
: >:
: >: copying two arrays is:
: >:
: >: set -A new_array -- "${old_array[@]}"
: >:
: >: compare with rc:
: >: new_array = $old_array
: >
: > Yes, but in ksh $array and ${array[0]} are synonymous. This allows you
: > to do many things. Indeed, the standard method in ksh88 of not
: > having ENV set for scripts depended on this.
:
: Yes $var is either a string, a list of pattern, the 0th element of an array...
: That's not what I call a consistant typing. Compare with rc:

If I want consistent typing, I'll write in a higher level language. Note that
the only variable type in UNIX is a string, regardless of its contents.

:
: Default (and only) variable type in rc is array:


: var = 'string'
: is actually a shortcut for
: var = ('string')
:
: It's the same in ksh93 but who knows it?
:
: in rc, there's no word splitting of variable expansion, when you do
:
: command $var
:
: it's the same as ksh's:
: command "${var[@]}"
:
: In ksh, "command $var" passes the element of indice 0 of $var on
: which is performed filename generation, tilde expansion and
: word splitting.
:
: zsh arrays and string variables are of different types.
:
: var1="string" # defines a "scalar" type variable
: var2=("string") # defines a "array" type variable
:
: command $var1
: # passes *one* "scalar" argument to command
:
: command $var2
: # passes as many arguments as there are elements in the array to
: # command.
:
: Don't you find it a more intuitive and consistant behavior?

I find ksh's methods consistent enough.
:
: [...]


: > Gee, I did it for 11 years. Lots of dtksh scripts too, used by hundreds of users
: > with no defects reported.
:
: I'm sure *you* can write correct scripts. But admit ksh93
: doesn't "ROCK" (as it was what I was replying to) and shouldn't
: be advised to a beginner and certainly not for "programming".

I'm sorry, but I do think it ROCKS. And I certainly believe
it's suitable for programming. And when my son wanted to start
programming, that's exactly what I started him with.

:
: >: 5- command substitution removes too many NLs


: [...]
: > This is documented. You have a choice - every trailing newline or none.
: > Having every trailing newline would create more problems than having none.
:
: So, you agree?

I don't think a defined characteristic should present a problem.

:
: >: So, you'd think


: >:
: >: print -r -- "$(cmd)"
: >: outputs the same as
: >: cmd
: >
: > Not if you read the man page.
:
: But "yes", if you'd expect ksh programming to be a bit intuitive
: and consistant.

But then how would you deal with all the unwanted newlines? Again,
it's a design decision. All languages employ them.

:
: >: It doesn't, except when the value returned by the command doesn't


: >: end with a newline character.
: >:
: >: To work around this, you have to do:
: >: var=$(cmd; echo .)
: >: var=${var%?} var=${var%?}
: >
: > I wouldn't know. In 11 years it never came up.
:
: That's again about the "unlikely". As long as you don't write
: software for powerplants or CGIs, you may not care about
: writing approximate software that work most of the time.

Like I said, I wouldn't write airplane software in ksh. But I wouldn't
write it in ANY interpreted language - not rc, not zsh, not perl.
I don't know of anyone who would.

If by CGI you mean Common Gateway Interface, I've written plenty
of bullet-proofed cgi scripts in ksh. We chose ksh over perl because
there are a lot more people who can read ksh than perl. Perl would
have been my preference because of the modules. C'est la...

:
: I wouldn't write powerplant software in perl either. But many


: write CGI scripts in perl, perl being a programming language
: (with its flaws too, but far less than in ksh).
:
: >: 6- danger of using a shell both as a shell and as a programming
: >: language.
: [...]
: >: In a shell, most forget to do
: >: cd -- "$var" || exit

I don't think anyone would ever write that. You mean you'd want to
exit the shell if your cd failed. That could be tiresome.

: >: because they are used to only typing


: >: cd $var
: >: at the prompt and look at the result.
: >
: > You can't blame bad programming technique on anything but bad
: > programmers. "Look at this stupid gun. I put it to my head and pull the trigger
: > and ..."
: >
: > You can't both argue that ksh is not a programming language and then blame it
: > for people using it in a manner not appropriate for a programming language.
:
: Yes, but you and David Korn and I and every one fall in that
: trap.

Actually I don't. If I'm changing to a directory I don't know exists I

cd -- "$dir" || fatal "Can't change to $dir"

where fatal is an error routine that prints a message and exits.

:
: >: Moreover, commands are often made to be run interactively. The


: >: information on failure is a text intended for a human on standard
: >: error. So, generally, a script will be unable to parse that error
: >: message to take appropriate action.
: >:
: >: That's one of the most important reasons why a shell shouldn't be
: >: seen as a programming language.
: >
: > Oh gee, and there's no way we could capture stderr!
:
: Yes, uneasily, making scripts even more illegible, you'd have to
: cope with message localization, write a complex parser for every
: error. In other programming languages, library functions return
: a errno suitable for analysis by an /automate/ (and *then* you
: display an error message to the human user).

Well, that's not a problem of the shell now, is it. it depends on the
program you are calling. And I fail to see how any other shell could
improve upon that.

Shell library
: functions are commands whose output is directly intended to a
: human user, in a narrower extent to an automate (the exit status
: is often limited to success/error).

One of the advantages of ksh is you need to depend on so many fewer
external programs.
:
: [...]

No, because your arguments fly in the face of massive amounts of
experience. You find these extreme examples that in general
people don't experience (otherwise I think you would hear massive complaints).
:
: [...]


: >: 11- behavior of a script depends on its name!
: >:
: >: cd /tmp
: >: PATH=$PATH:
: >: echo '#! /usr/local/bin/ksh93' > script.ksh
: >: chmod 755 script.ksh
: >: ln -s script.ksh ./--man
: >: ln -s script.ksh ./-i
: >:
: >: "script.ksh", "-i" and "--man" are supposed to be the same script.
: >: However, the first one does nothing, the second runs an interactive
: >: shell, and the third one displays a short ksh93 man page!
: >
: > Again, is this really a problem?
:
: Not really, except in the case of setuid scripts (check the
: unix-faq). And you'll have problem with perl or python too,
: that's more a shebang issue than a shell issue.

And how many systems support setuid scripts? For that matter, does
ksh support setuid scripts? Anyone fooling with setuid scripts has
already one foot deep in alligator infested waters.

:
: > Guess what, you can't name a script


: > "while" or "test" or "for" etc. either.
:
: Sure I can, why couldn't I?

That's true, you can, But you can only explicitly path them:

$ cat while
#!/usr/bin/ksh
echo OK
$ ./while
OK
$ ksh while
OK
$ while
<
$ 'while'
OK

:
: That's even another arguments toward always quoting every


: argument.
:
: If I write:
:
: 'while' 'arg1' 'arg2'
: I kind of force the typing. I'm sure 'while' is taken as a
: command argv[0]. Maybe in ksh93p, there will be a new "perhaps"
: keyword, so you'll be happy that your scripts correctly written
: as:

Look at the definition of keyword in the man page for why 'while' is taken
as a command.

:
: function 'perhaps' {


: 'typeset' 'IFS= '
: 'print' '-r' '--' "Maybe I should $*"
: }
: 'perhaps' 'try another shell'
:
: will continue to work.
:
: [...]

Again, your objections are just silly now.
: >: 12- Documentation.


: >:
: >: ksh93 documentation is disseminated. The man page doesn't describe
: >: half of the behavior. To know about a builtin, you have to run ksh93
: >: and issue the (undocumented):
: >
: > It certainly is not undocumented. Under "BUILTIN COMMANDS" it clearly
: > states to enter "cmd --man" to get a man page for the command.
:
: Yes --man is. I missed that. "--api", "--author", "--html",
: "--about", "--nroff", "--long", "--short", "--help", "--keys"...
: are not.

Again, those are not features used in programs. But thanks for pointing them out.
:
:
: >:
: >: builtin --man


: >: or
: >: builtin --help
: >: or
: >: builtin --html
: >: (yes all the documentation is in the binary ksh93 executable! This
: >: certainly goes against most system documentation policy)
: >
: > Not against mine. I've always included documentation with everything
: > I've written.
:
: I generally include it in a man page. To learn about a software,
: I type "man <software>", not "<software> --man 2>&1 | ${PAGER-more}"

Which would leave me out in the cold. I bought a Lindows system from Wal*Mart
thinking I could run some M$ under Wine (the original Lindows goal). Instead I
get a stripped down Linux install with no man command or man pages. About the
only thing I can get man pages for are the ksh I downloaded from kornshell
because they are builtin. So I would have to call this a feature, not a problem.

:
: >:
: >: That doesn't work with every builtin (echo, :),


: >
: > Of course not. Only with commands that already take arguments.
: > Otherwise you would not be backwards compatible.
:
: That's why I say, that was a silly way to do it. and that bash's
: help builtin was better.
:
: > and for keywords
: >
: > keywords don't take arguments. They are part of the syntax.
:
: Yes, same as above. In bash, you can do "help for".

Or you can just read the man page. Again, nothing to do with
programming.
:
: >
: >: (for, while...). At least, even if it's arguable to put the


: >: documentation in the code, bash chose a dedicated builtin for that
: >: (help) and has a full man/info/html page.
: > different strokes for different folks
:
: Yes, the poster I replied to said "ksh93 was far superior to
: bash". Not on this.

ps -ef | while read -A Data;do USER[${#X[@]}=${Data[0]} ...;done

and still have the USER array populated after the while makes it far superior.
coprocesses makes it far superior.
FPATH makes it far superior.


:
: >: 13- Poor interactive shell


: >:
: >: shell vocation is to be used at prompt. ksh93 is one of the most
: >: poorly featured one: no programmed (or even programmable)
: >: completion, no incremental search, poor history facilities, poor
: >: extended key handling, poor prompt facilities
: >
: > No, different prompt facilities. You just don't know how to use them, appparently.
:
: No, I didn't even try. I had just to compare zsh's prompt
: expansion, prompt themes with ksh's.
:
: >
: > , no multiline command
: >: editing,
: >
: > Of course there is. You can even choose the editor.
:
: No, I meant a shell command line editor; you can't search the
: shell history when you've started vi, for instance.
:
: > no spelling correction, no rc file except via the dumb ENV
: >
: > What's so dumb about it?
:
: Many reasons. First the name. Who can imagine a less specific
: name than "ENV" for an environment variable. Every program could
: have used this name for a variable used to set up its
: environment. I would have expected at least KSH_ENV or
: KSH93_ENV.

Gee, when ksh was written you had sh and csh as competitors. Silly
of David to not consider evrything that might possibly happen.
:
: Its content is read for every shell (interactive or script
: interpreters).

Only for ksh88. ksh93 only sources env for interactive shells.

By "rc" file, I meant a shell customization file.
: If, at prompt, I like the noclobber option, and put it in the
: ENV file, I'll break most scripts.

Not with ksh93. And real ksh programmers new how
to protect themselves from ENV being set for scripts
(by setting it indirectly) or having their scripts invoke it (by using the -p option)
:
: This var is shared for too different purposes (more if you


: consider this variable is read by every POSIX compliant shell),

most of which were developed by adapting the ksh source.

: why not having used two separate mechanisms (look zsh and its


: zshenv and zshrc files).
:
: That's why you see ugly things like
:
: export INTERACTIVE_ENV="$HOME/.kshrc"
: export ENV='${INTERACTIVE_ENV[(Z$-=0)+(Z=1)-Z${-%%*i*}]}'
:
: (which doesn't allow for a ENV for non-interactive shells).

Which you shouldn't do. It's not structured.

:
:
: > At least ksh's policy doesn't violate


: > structured programming tenets.
:
: How can you speak of "structured" which such a fuzzy syntax...
:
: [...]
: >: for i in 1 2
: >: {
: >: print -r -- "$i"
: >: }
: >:
: > cool
:
: Isn't it? It's in every Bourne like shell.

And the problem is?

:
: [...]


: >: 16- arithmetic expansion that depends on locale
: >:
: >: #! /usr/local/bin/ksh93 -
: >: typeset -F pi=3.14159265359
: >: echo "cos(pi/2) is $(( cos(pi/2) ))"
: >:
: >: when run in a french locale gives:
: >:
: >: ksh93: .[2]: typeset: 3.14159265359: arithmetic syntax error
: >: because in french, the decimal point is a comma.
: >
: > Good to know.
:
: And I didn't speak of all the issues related to LC_COLLATE, LC_CTIME...
: In other programming languages, you have to explicitely activate
: localization. In shells, you have to disable it.

Again, not a problem for most people.

:
: >: 17- "export var" when var is unset doesn't put "var" in the environment.


: >
: > And it shouldn't. It only marks it for export. "export var=" will put it in the
: > environment.
:
: Yes, you're right even if that depends on how you interpret POSIX:
:
: The shell shall give the export attribute to the variables
: corresponding to the specified names, which shall cause them
: to be in the environment of subsequently executed commands.
:
: Most modern shells seem to agree with you.

So the problem is?
:
: [...]


: >: 19- arrays start at index 0
: [...]
: > Oh, c'mon - that's really picky.
:
: But that's annoying. That's a small one of ksh's many
: inconsistancies.

It's not inconsistent with C. And "$@" does not
constitute an array. So who exactly is it inconsistent with?

:
: [...]


: >: Compare with "es":
: [..]
: >: or zsh:
: [...]
: > So use them instead.
:
: Of course I do. My point here is to say that no, we can't say
: "KSH93 ROCKS", use zsh instead for interactive shell, and a
: programming language for programming stuff, ksh93 is good at
: neither one.

Tried zsh. Didn't like it. It's one of those bathtub solutions - it tries
to do too much. It's simply way too complicated, like emacs. I had
a buddy who loved emacs, loved to say how it improved his
productivity. Good thing too, since he spent 6 hours a day
palying with it instead of doing his assigned work. When learning
about a shell takes more effort than it's worth, why bother?

And if you're talking about processing lsof or ps output, or
peeking at someone else's screen, or firing up a toolbar or
a list widget, or operating on an Oracle database, or backing
up directories, or distributing software,
then (dt)ksh is all the shell you need
:
: [...]


: >: 24- exit status policy different from any other shell's
: >:
: >: $? contains 256 + signum when a command was killed instead of 128 +
: >: signum in every other shell.
: >
: > Every other shell got it wrong?
:
: No. I prefer the ksh93 way, but it breaks compatibility
:
: [...]
: > , kind of regular
: >: expressions, math library function...), but they are brought over a
: >: really broken basis. You don't build a spaceship on top of a bicycle
: >: frame!
: >
: > But the Wright bros built an airplane that way. Look, you may not
: > want to fly an airplane on a ksh script, but it's damn useful in a hundred other
: > ways.
:
: Yes, in response to "KSH93 ROCKS", I say no,
: It's a really poor bicycle, use zsh instead.
: It's a really broken airplane, use python instead.

Yeah, use python. Justify it to your bosses. install it and maintain it
yourself. Convince your bosses that if you get hit by the beer truck
they won't be left with a lot of code they'll have to find a rare
export to support. I've made, and lost, those arguments.
That's why I program in ksh

Dan Mercer
dme...@mn.rr.com

:
: --
: Stéphane


Stephane CHAZELAS

unread,
Jun 26, 2003, 3:17:36 PM6/26/03
to
Dan Mercer wrote:
[...]

>: Are you saying that David Korn is an unitiated or ignorant ksh
>: programmer? I wouldn't have dared ;).
>:
>: He wrote:
>: getopts '[-]' opt --???man
>
> In a man page, though my man page says "--??man" and "--man" works.
> Again, this is a problem with any globbing. Also note that getopts --man
> won't be called in a script.

The code above is taken from
http://www.research.att.com/~dgk/ksh/script/env
a script made by David Korn, put on his home page (maybe to
demonstrate the /power/ of ksh93).

[...]


> It's the way I've done it for 12 years. And certainly it's been mentioned
> in this group a hundred times (at least 50 by me)

Yes, another way is

set -- [*] *
case "$1$2" in
"[*]*") ;;
*) shift; for i
do ...
done;;
esac

Almost as legible ;).

[...]


>: 3. The newtest ([[ ... ]]) operator -a file is obsolete.
>: Use -e instead.

[...]


> Yeah, I can never keep straight those two and I was too lazy to look it up.
>
>:
>: Although I agree it was more accurate. It doesn't check for
>: file existance, but for file accessibility.
>
> No, it tests for existance. It returns true even if the file has
> no permission bits.

By accessibility, I meant the ability to at least stat the file.
You can actually list a directory content without being able to
stat the files. If the file is not "stat"able (you don't have
"x" permission on the directory for instance), [[ -a file ]]
will return "false", that was not in the sense of access(2).

But to list the content of the current directory, you must have
"x" permission on it, so that doesn't apply in this very
example.

Only in example like:

$ mkdir 1; touch 1/{a,b,c}; chmod 444 1
$ echo 1/*
1/* 1/a 1/b 1/c
$ for f in 1/*; do [[ -e $f ]] && echo "$f"; done
$ set -- 1/[*] 1/*;case "$1$2" in "1/[*]1/*");;*)shift;for i;do echo "$i";done;esac
1/*
1/a
1/b
1/c

[...]


>: for file in *(N); do
>: ...
>: done
>:
>
> Again, this is not a major problem and one easily dealt with, as are all error
> conditions.

I consider it is, as you get no warning. Your script will work
for a while, and because of the ambiguity of "patterns" (they
are no more patterns when they match nothing) you may run into
troubles.

[...]


>: I provided one (courtesy of David Korn).
>
> You provided one obscure example that does not occur in scripts.

I provided an example from a script by David Korn.

> Show an example that might occur in a script.

A very common example is the:

find /dir -name *.html -print

We see sometimes in this NG.

If there's no html file in the current directory, it will work
OK. if there's one file in the current directory, it will (without
any error or warning) return an incorrect result, if there are
more, it will return an error.

[...]


> No, "time" and "!" do not take arguments, any more than "for" or "while"
> do. "time" runs the pipeline following it and displays the timing for it. If it were
> a builtin, it would only run the first sequence in the pipeline. The same thing goes for
> ! - if it were not a keyword, it would only reverse the truth of the first segment
> of a pipeline, not the whole pipeline.

Yes, you know, I know why "!" can't be a builtin. Who else? For
time, there's a "/usr/bin/time" command, if you don't read the
ksh man page in detail or issue a "type time", you may think
it's a command or builtin.

And what about the typeset/export builtins/keywords?

But I fear we're nitpicking here.

[...]


>: Other examples from Mr Korn. Again in its "env" script.
>: To clear the environment "typeset +x $(typeset +x)"
>: It only clears shell variable like environment variables, and
>: not the "_" one (well it's still exported to the next command
>: run).
>
> No, you are wrong on this. The sequence above clears the export
> flag. But "$_" is one of the inherent variables, like "$!" "$$" "$PPID"
> in every shell. It is automatically marked for export (why, I don't know).
>
> So again, this is a misunderstanding on your part, not a failure on Korn's.

There are two things about $_. First, the $_ *shell* variable
(not exported) is the last argument of the last command run.

Then, ksh passes a "_" environment variable to every process it
execs containing the path of the program.

_=1 env
returns "_=/usr/bin/env"

In zsh, "_" is readonly, you can't modify or unset it. But
that's also nitpicking.

>: Another one in the same file:
>:
>: command unset $OPTARG 2> /dev/null
>:
>
> Korn's example are just that - quick and dirty examples

If there's somewhere where you have not to be dirty, it's in
example. An example is something intended to be reproduced.

> not full
> fledged production code. The example file you give even has a commented
> out line of code. Since the globbing chars do not form legitimate
> variable names, it's unlikely you would be trying to unset a variable
> with that name.

They are legitimate environment variable names (and because they
are not legitimate *shell* variable name, one may want to unset
them).

But my point was that even the most experienced shell programmer
can't help making those kind of errors because of the nature of
ksh syntaxe and because it is too much permissive.

[...]


>: >: Each time you want to split a string, you have to disable filename
>: >: generation (on by default).
>: >
>: > Again, I need to see an example of something broken.
>:
>: For example, one of your posts:
>: Message-ID: <Cm6Fa.2548$fe.1...@twister.rdc-kc.rr.com>

[...]


> So you change the above to:
>
> function split {
> set -f

[...]

Yes, that was exactly my point, the point you needed an example
for.

[...]


> The actual split function I employed at work is far longer and
> more bullet proof.

And how much time did you spend writing it. If you had been
using perl, awk, python, there was already a function to do it.
I'd be curious to see your bullet proof split command. How does
it deal with IFS white spaces?

[...]


> If I want consistent typing, I'll write in a higher level language. Note that
> the only variable type in UNIX is a string, regardless of its contents.

environment variables you mean? ksh have several variable types
(string/array/patter, integers, floating point, hashes...)
as you know.

[...]


>: >: 5- command substitution removes too many NLs
[...]

> But then how would you deal with all the unwanted newlines?

Do you have an example where there are additional unwanted
newlines beside the trailing one?

Anyway, to remove trailing newlines:

var=${var%"${var##*[!
]}"}

> it's a design decision. All languages employ them.

Not the good one, to my mind. But note that I know every shell
works like that, that's not a ksh only issue.

[...]


> If by CGI you mean Common Gateway Interface, I've written plenty
> of bullet-proofed cgi scripts in ksh. We chose ksh over perl because
> there are a lot more people who can read ksh than perl. Perl would
> have been my preference because of the modules. C'est la...

Can you guarantee it's bullet proof?

David Korn also has a
http://www.research.att.com/~dgk/ksh/script/cgi-lib.ksh

I didn't read it in much details, but it's likely that, by
positionning some specific "Cookie" header, one may be able to
know the content of any directory on the server:

function cgi_cookie
{
typeset cookie=$1 name val c IFS=';'
set -- $cookie
[...]

He forgot the "set -f".

[...]
>: >: In a shell, most forget to do
>: >: cd -- "$var" || exit
>
> I don't think anyone would ever write that. You mean you'd want to
> exit the shell if your cd failed. That could be tiresome.

Maybe not exiting the shell, but at least doesn't continue as if
you had managed to go in that directory of course (as the
remaining of the script assumes "$var" is the new current
directory).

[...]


>: Yes, but you and David Korn and I and every one fall in that
>: trap.
>
> Actually I don't. If I'm changing to a directory I don't know exists I
>
> cd -- "$dir" || fatal "Can't change to $dir"

Note that "cd" already displays the error message.

>
> where fatal is an error routine that prints a message and exits.

Great, that should be teached in every shell programming book.
And every one should read a shell programming book before
writing scripts. I fear it's not always the case.

[...]


>: Thanks, why? Because I try to imagine ways how to do programming
>: with shells? I think I have to agree, that's a bit silly.
>
> No, because your arguments fly in the face of massive amounts of
> experience. You find these extreme examples that in general
> people don't experience (otherwise I think you would hear massive complaints).

Yes because few people do shell programming for complex
application, and so that it remains so, I prefer posting those
kind of warnings when someone advertises shell programming.

ksh93 has been quite unknown so far. As it is now released with
sources, many might want to try it and beleive its claim for
being a "powerful programming language".

[...]


>: Not really, except in the case of setuid scripts (check the
>: unix-faq). And you'll have problem with perl or python too,
>: that's more a shebang issue than a shell issue.
>
> And how many systems support setuid scripts? For that matter, does
> ksh support setuid scripts? Anyone fooling with setuid scripts has
> already one foot deep in alligator infested waters.

Agreed, and mostly because it's difficult to write reliable
scripts.

[...]


>: Yes, same as above. In bash, you can do "help for".
>
> Or you can just read the man page. Again, nothing to do with
> programming.

But ksh man page is not complete (see the getopts description in
the man page). And my post was not only about programming.

[...]


> ps -ef | while read -A Data;do USER[${#X[@]}=${Data[0]} ...;done
>
> and still have the USER array populated after the while makes it far superior.
> coprocesses makes it far superior.
> FPATH makes it far superior.

;) OK, my turn:

~/.bashrc makes bash superior (well, actually, zsh's way is much
more consistent).

Its builtin command line editor makes it far superior

history expansion makes it far superior (well, I don't like nor
use it, even in zsh, but one could say that).

prompt facilities make it superior.

programmable completion makes it superior

PIPESTATUS makes it superior

Note that I use neither bash nor ksh93, as you probably have
already guessed. I have to agree bash is not much better than
ksh. Most of the argument I wrote also apply to bash.

[...]


> Only for ksh88. ksh93 only sources env for interactive shells.

Right, I stand corrected. But ENV is still read by
non-interactive POSIX compliant shells.

[...]
>: >: for i in 1 2
>: >: {
>: >: print -r -- "$i"
>: >: }
>: >:
>: > cool
>:
>: Isn't it? It's in every Bourne like shell.
>
> And the problem is?

Not really important. Just what I said in my original post.

[...]


>: And I didn't speak of all the issues related to LC_COLLATE, LC_CTIME...
>: In other programming languages, you have to explicitely activate
>: localization. In shells, you have to disable it.
>
> Again, not a problem for most people.

In the US you mean? When is ksh93 ready for unicode?

[...]


>: >: 17- "export var" when var is unset doesn't put "var" in the environment.
>: >
>: > And it shouldn't. It only marks it for export. "export var=" will put it in the
>: > environment.
>:
>: Yes, you're right even if that depends on how you interpret POSIX:
>:
>: The shell shall give the export attribute to the variables
>: corresponding to the specified names, which shall cause them
>: to be in the environment of subsequently executed commands.
>:
>: Most modern shells seem to agree with you.
>
> So the problem is?

None, I just say you were right and I was wrong.

[...]


> Tried zsh. Didn't like it. It's one of those bathtub solutions - it tries
> to do too much. It's simply way too complicated, like emacs. I had
> a buddy who loved emacs, loved to say how it improved his
> productivity. Good thing too, since he spent 6 hours a day
> palying with it instead of doing his assigned work. When learning
> about a shell takes more effort than it's worth, why bother?

Even without reading the man page, you benefit from zsh. Its
syntax, key binding is much intuitive, it's completion system
powerful and easy to use. It's globbing facilities are worth
learning.

You may want to give zsh 4.0 a try. Completion is now mature.

A question Dan, as you seem to know ksh93 quite well, is this a
bug or feature:

$ a=" ."
$ printf "<%s>\n" ${a#' '}
<>
<.>

I don't understand the result.

--
Stéphane

Dan Mercer

unread,
Jun 26, 2003, 10:56:55 PM6/26/03
to

"Stephane CHAZELAS" <stephane...@yahoo.fr> wrote in message news:slrnbfmhel.7oe.s...@pcchazelas.free.fr...

: Dan Mercer wrote:
: [...]
: >: Are you saying that David Korn is an unitiated or ignorant ksh
: >: programmer? I wouldn't have dared ;).
: >:
: >: He wrote:
: >: getopts '[-]' opt --???man
: >
: > In a man page, though my man page says "--??man" and "--man" works.
: > Again, this is a problem with any globbing. Also note that getopts --man
: > won't be called in a script.
:
: The code above is taken from
: http://www.research.att.com/~dgk/ksh/script/env
: a script made by David Korn, put on his home page (maybe to
: demonstrate the /power/ of ksh93).

It's a sample. It even contains commented out code. His computer
has an env command.

:
: [...]

So somebody shoots themselves in the foot. You can do that with anything.

:
: [...]


: > No, "time" and "!" do not take arguments, any more than "for" or "while"
: > do. "time" runs the pipeline following it and displays the timing for it. If it were
: > a builtin, it would only run the first sequence in the pipeline. The same thing goes for
: > ! - if it were not a keyword, it would only reverse the truth of the first segment
: > of a pipeline, not the whole pipeline.
:
: Yes, you know, I know why "!" can't be a builtin. Who else? For
: time, there's a "/usr/bin/time" command, if you don't read the
: ksh man page in detail or issue a "type time", you may think
: it's a command or builtin.

Again, DK is not responsible for the problems of people who won't
read a man page. You can't do anything in zsh without reading a dozen\man files or perl
without reading a book.

:
: And what about the typeset/export builtins/keywords?


:
: But I fear we're nitpicking here.
:
: [...]
: >: Other examples from Mr Korn. Again in its "env" script.
: >: To clear the environment "typeset +x $(typeset +x)"
: >: It only clears shell variable like environment variables, and
: >: not the "_" one (well it's still exported to the next command
: >: run).
: >
: > No, you are wrong on this. The sequence above clears the export
: > flag. But "$_" is one of the inherent variables, like "$!" "$$" "$PPID"
: > in every shell. It is automatically marked for export (why, I don't know).
: >
: > So again, this is a misunderstanding on your part, not a failure on Korn's.
:
: There are two things about $_. First, the $_ *shell* variable
: (not exported) is the last argument of the last command run.

sometimes.
:
: Then, ksh passes a "_" environment variable to every process it


: execs containing the path of the program.
:
: _=1 env
: returns "_=/usr/bin/env"
:
: In zsh, "_" is readonly, you can't modify or unset it. But
: that's also nitpicking.
:
: >: Another one in the same file:
: >:
: >: command unset $OPTARG 2> /dev/null
: >:
: >
: > Korn's example are just that - quick and dirty examples
:
: If there's somewhere where you have not to be dirty, it's in
: example. An example is something intended to be reproduced.


Yeah, but who's going to try to unset a variable with an invalid
name. GIGO applies there.
:
: > not full


: > fledged production code. The example file you give even has a commented
: > out line of code. Since the globbing chars do not form legitimate
: > variable names, it's unlikely you would be trying to unset a variable
: > with that name.
:
: They are legitimate environment variable names (and because they
: are not legitimate *shell* variable name, one may want to unset
: them).

I don't think ksh allows invalid env names. You can use env to
create them for dumb programs that like to break the rules, but
I don't remember if ksh supported them. I'd check, but my
noisy Linux machine is shut down,

:
: But my point was that even the most experienced shell programmer


: can't help making those kind of errors because of the nature of
: ksh syntaxe and because it is too much permissive.
:
: [...]
: >: >: Each time you want to split a string, you have to disable filename
: >: >: generation (on by default).
: >: >
: >: > Again, I need to see an example of something broken.
: >:
: >: For example, one of your posts:
: >: Message-ID: <Cm6Fa.2548$fe.1...@twister.rdc-kc.rr.com>
: [...]
: > So you change the above to:
: >
: > function split {
: > set -f
: [...]
:
: Yes, that was exactly my point, the point you needed an example
: for.
:
: [...]
: > The actual split function I employed at work is far longer and
: > more bullet proof.
:
: And how much time did you spend writing it. If you had been
: using perl, awk, python, there was already a function to do it.
: I'd be curious to see your bullet proof split command. How does
: it deal with IFS white spaces?

Well, perl and awk started out as text processors. That isn't
what the shell is all about.
:
: [...]


: > If I want consistent typing, I'll write in a higher level language. Note that
: > the only variable type in UNIX is a string, regardless of its contents.
:
: environment variables you mean? ksh have several variable types

That's what I intended to type.

: (string/array/patter, integers, floating point, hashes...)

But it's not really typing. It's much looser than that.

: as you know.


:
: [...]
: >: >: 5- command substitution removes too many NLs
: [...]
: > But then how would you deal with all the unwanted newlines?
:
: Do you have an example where there are additional unwanted
: newlines beside the trailing one?

That is the unwanted one.
:
: Anyway, to remove trailing newlines:


:
: var=${var%"${var##*[!

: ]}"}

Which you would have to do after almost all command substitutions.

if [[ "$(somecmd)" = somevalue ]]

would become really ugly.
:
: > it's a design decision. All languages employ them.


:
: Not the good one, to my mind. But note that I know every shell
: works like that, that's not a ksh only issue.
:
: [...]
: > If by CGI you mean Common Gateway Interface, I've written plenty
: > of bullet-proofed cgi scripts in ksh. We chose ksh over perl because
: > there are a lot more people who can read ksh than perl. Perl would
: > have been my preference because of the modules. C'est la...
:
: Can you guarantee it's bullet proof?

Well, our test group was pretty inventive and they hammered them pretty hard.

:
: David Korn also has a

Well, I've seen and done some pretty powerful things with it.

:
: [...]


: >: Not really, except in the case of setuid scripts (check the
: >: unix-faq). And you'll have problem with perl or python too,
: >: that's more a shebang issue than a shell issue.
: >
: > And how many systems support setuid scripts? For that matter, does
: > ksh support setuid scripts? Anyone fooling with setuid scripts has
: > already one foot deep in alligator infested waters.
:
: Agreed, and mostly because it's difficult to write reliable
: scripts.

I remember one setuid script that ssaved my bacon. I sat down at the
console to apply a patch tape for ksh and another to remove the setuid
script. Someone had stupidly changed root's shell to ksh. A bad SCSI
caused a panic before the ksh finished upgrading - I had only
half a ksh. You couldn't get in as root or get an su or change /etc/passwd.
But I could exploit the su script to give me a root sh and fix passwd.

:
: [...]


: >: Yes, same as above. In bash, you can do "help for".
: >
: > Or you can just read the man page. Again, nothing to do with
: > programming.
:
: But ksh man page is not complete (see the getopts description in
: the man page). And my post was not only about programming.
:
: [...]
: > ps -ef | while read -A Data;do USER[${#X[@]}=${Data[0]} ...;done
: >
: > and still have the USER array populated after the while makes it far superior.
: > coprocesses makes it far superior.
: > FPATH makes it far superior.
:
: ;) OK, my turn:
:
: ~/.bashrc makes bash superior (well, actually, zsh's way is much
: more consistent).
:
: Its builtin command line editor makes it far superior
:
: history expansion makes it far superior (well, I don't like nor
: use it, even in zsh, but one could say that).
:
: prompt facilities make it superior.
:
: programmable completion makes it superior
:
: PIPESTATUS makes it superior

Well, PIPESTATUS is the only one of those I would agree on.
However, even PIPESTATUS may not be reliable all the time.
If PROMPT_COMMAND is set, PIPESTATUS will be set
to the exit status of the PROMPT_COMMAND pipeline,
not the last typed command.
:
: Note that I use neither bash nor ksh93, as you probably have

: I don't understand the result. ${a#' '}ought to be quoted.
I had a dtksh script, built on an old version of ksh93, that
used to crap out on one statement. If I put in a print statement,
it would work. If I did set -x, it would work. I finally put in
a ":" on the previous line and , voila, it worked. Now it's possible
I introduced the problem by adding my own builtins. The method
for agging builtins changed between dtksh and current ksh93's.

Dan Mercer
dme...@mn.rr.com


I don't either. Probably a bug
:
: --
: Stéphane


Stephane CHAZELAS

unread,
Jun 27, 2003, 3:16:56 AM6/27/03
to
Dan Mercer wrote:
[...]
>: >: >: 5- command substitution removes too many NLs
>: [...]
>: > But then how would you deal with all the unwanted newlines?
>:
>: Do you have an example where there are additional unwanted
>: newlines beside the trailing one?
>
> That is the unwanted one.

But I suggested that only the trailing one should be removed,
not every trailing one.

Note that "rc" behavior is:

var = `{cmd}

splits "cmd" output on ifs chars (sequence of ifs chars is same
as one ifs char, trailing and leading ifs chars are ignored
(there's nothing special with NLs, and no difference between
white space and ordinary chars))

You can specify the ifs list:
var = ``(:){cmd}
or
var = ``(){cmd}

so,

printf %s ``(){cmd}

outputs the same as.

cmd

The problem is that it's not easy to remove the trailing NL with
"rc". Easier with "es".

[...]


> I remember one setuid script that ssaved my bacon. I sat down at the
> console to apply a patch tape for ksh and another to remove the setuid
> script. Someone had stupidly changed root's shell to ksh. A bad SCSI
> caused a panic before the ksh finished upgrading - I had only
> half a ksh. You couldn't get in as root or get an su or change /etc/passwd.
> But I could exploit the su script to give me a root sh and fix passwd.

:)

--
Stéphane

llewelly

unread,
Jun 27, 2003, 10:03:30 AM6/27/03
to
Stephane CHAZELAS <stephane...@yahoo.fr> writes:

> Walt Fles wrote:
>> Korn Shell 93 ROCKS!
>> It is far superior from bash or bourne.
> [...]
>
> I see more and more often in this newsgroup enthusiastic posts about the
> ksh93 shell. I'd like to temper it a bit. I consider ksh and especially
> ksh93 one of the worst shell ever written, and especilly, its claim to
> be a good choice for a programming language is ridiculous. By no mean
> can it be compared to interpreted languages like perl/python/ruby/tcl.
>
> Making complex applications with it is probably the worst choice
> possible. Below are some unsorted arguments that come to my mind for
> what I say. Note that some of them also apply to other Bourne like
> shells like bash or zsh or to shells in general.

[snip long argument aganst ksh93 and other shells]


> ksh93 comes with features that could appear useful for a programming
> language (pre-compilation, inline documentation, TCP socket support,
> disciplines (I've yet to see what it can be useful to), kind of regular
> expressions, math library function...), but they are brought over a
> really broken basis. You don't build a spaceship on top of a bicycle
> frame!
>
> Thanks for reading, feel free to argue on all this. Of course, I exposed
> only the arguments *against* writing shell scripts. There are toward
> writing scripts in some circumstances, but generally not with the ksh93
> shell.

[snip]

There are two reasons to use the bourne shell:

(a) It is availible on every unix. (except unix <= v6)

(b) On most unices, it is used to write system scripts. (Linux is
the only exception I can think of offhand - and it uses
bash.)

I think these reasons are important, and I think these are the primary
reasons ksh93 (and bash, and probably zsh) have the nature they
do. I've met people who've replaced FreeBSD's sh with ksh93, and
claim to have had no problems, and linux, of course, uses
bash. However it's unfortunate that the people extending sh to
make ksh93 or bash didn't focus on making sh safer and saner.

(a) is not as nice as one might hope; on many unices sh does not run
in posix mode by default, so writing sh scripts portable to more
than two systems is a kind of hideous black art.

(b) is not as strong as one might think; though it would take major
surgery to replace all the system scripts of a unix, both linux
and freebsd have 'from scratch' groups whose help would (I assume)
make the process a lot more straight forward.

I won't object to any of your complaints; I agree with every one of
them, though a few are IMO unimportant.

Finally: My first computer job included occasional maintenance of a
multi-hundred line system of dos batch files. Based on this
experience I will claim that every unix shell I'm familiar with,
yes, even csh, is less horrible than the dos shell.


Stephane CHAZELAS

unread,
Jun 27, 2003, 10:33:28 AM6/27/03
to
llewelly wrote:
[...]

> There are two reasons to use the bourne shell:
>
> (a) It is availible on every unix. (except unix <= v6)
>
> (b) On most unices, it is used to write system scripts. (Linux is
> the only exception I can think of offhand - and it uses
> bash.)

Don't confuse Bourne and POSIX compliant shells. The Bourne
shell is not POSIX compliant. Very few unices nowadays have a
Bourne shell as /bin/sh.

On Free/Net/Open BSD (maybe also on MacOS X), /bin/sh is ash
(Almquist shell) based

On Linux, Hurd, /bin/sh is bash in posix mode (maybe dash
[debian almquist shell based on BSDs shell] on some systems).

On most commercial unices, it's a ksh88 or a ksh88 derived shell.

Note that bash is certainly not the least POSIX compliant one.

You may find the Bourne shell nowadays as "bsh" or
/usr/old/bin/sh. You won't find it on free Unices (or
unix-like if you prefer) as its code was never released (except
the very early Unix V7 one impossible to port to modern
systems). Note that since Unix V7, it evolved much (and in
to different branches in different systems).

See

http://www.uni-ulm.de/~s_smasch/various/bourne/
http://www.tuhs.org/
http://groups.google.com/groups?selm=1745%40fig.bbn.com&output=gplain

[...]


> (a) is not as nice as one might hope; on many unices sh does not run
> in posix mode by default

which ones? I agree that most are not completely POSIX
compliant, but I think they all try to be.

> so writing sh scripts portable to more
> than two systems is a kind of hideous black art.

Yes, especially when you have to support old systems.
But often the problems come from the utilities more than from
the shell.

--
Stéphane

Klaus Horsten

unread,
Jun 27, 2003, 12:26:47 PM6/27/03
to
> > For me it makes sense to learn bash without learning cygwin.
> [snip]
>
> I suspect this doesn't make sense for most people; most
> non-trivial shell-scripting examples in books and in availible
> working source rely extensively on basic unix file and text
> utilities.


You can decouple/separate bash from cygwin (under windows )without
loosing the complex functionality.

You just have to drop all the necessary exes into your self-created
bin-directory and tell windows where to find it.

Limits are only where there are no executables are available.

Example:
You can't use the dialog command under cygwin neither without cygwin
because nobody has compiled a dialog.exe so far (although the source
code for unix is available).


Klaus

Kenny McCormack

unread,
Jun 27, 2003, 12:41:33 PM6/27/03
to
In article <slrnbfol4q.9um.s...@pcchazelas.free.fr>,
Stephane CHAZELAS <stephane...@yahoo.fr> wrote:
...

>Don't confuse Bourne and POSIX compliant shells. The Bourne
>shell is not POSIX compliant. Very few unices nowadays have a
>Bourne shell as /bin/sh.

Sun.

>On Free/Net/Open BSD (maybe also on MacOS X), /bin/sh is ash
>(Almquist shell) based

Is "ash" POSIX compliant? I thought the whole point of ash was
super-minimal (I think even smaller/less-featured than Bourne).

I'm basing this on my experience with TomsRootBoot.

Stephane CHAZELAS

unread,
Jun 27, 2003, 12:55:06 PM6/27/03
to
Kenny McCormack wrote:
[...]

> Is "ash" POSIX compliant? I thought the whole point of ash was
> super-minimal (I think even smaller/less-featured than Bourne).

ash was not, it was released before the standard anyway. But
everyone is modifying it without even maintaining version
numbers. You find plenty of "ashes" around. The original one was
posted to comp.unix.sources (I gave the google URL in my
previous post).

Latest BSD sh and dash are on the way to become fully POSIX
compliant, as I've seen. You could say they are acceptably POSIX
compliant so far.

--
Stéphane

Kenny McCormack

unread,
Jun 27, 2003, 1:45:48 PM6/27/03
to
In article <slrnbfotg4.9um.s...@pcchazelas.free.fr>,

Stephane CHAZELAS <stephane...@yahoo.fr> wrote:
>Kenny McCormack wrote:
>[...]
>> Is "ash" POSIX compliant? I thought the whole point of ash was
>> super-minimal (I think even smaller/less-featured than Bourne).
>
>ash was not, it was released before the standard anyway. But
>everyone is modifying it without even maintaining version
>numbers. You find plenty of "ashes" around. The original one was
>posted to comp.unix.sources (I gave the google URL in my
>previous post).

Thanks for the info. I think my point is that I'd rather ash *not* be
POSIX - since the whole point of ash is to be small. Certainly that is
Tom O's perspective.

Stephane CHAZELAS

unread,
Jun 27, 2003, 5:44:24 PM6/27/03
to
Stephane CHAZELAS wrote:
[...]
> http://www.uni-ulm.de/~s_smasch/various/bourne/
[...]

Note that this address changed, the new one is:

http://www.in-ulm.de/~mascheck/bourne/

(Sven Mascheck happens to be a contributor to this newsgroup,
even though not very active these days).

--
Stéphane

Greg Andrews

unread,
Jun 27, 2003, 6:08:11 PM6/27/03
to
Stephane CHAZELAS <stephane...@yahoo.fr> writes:
>
>Don't confuse Bourne and POSIX compliant shells. The Bourne
>shell is not POSIX compliant. Very few unices nowadays have a
>Bourne shell as /bin/sh.
>
>On Free/Net/Open BSD (maybe also on MacOS X), /bin/sh is ash
>(Almquist shell) based
>
>On Linux, Hurd, /bin/sh is bash in posix mode (maybe dash
>[debian almquist shell based on BSDs shell] on some systems).
>
>On most commercial unices, it's a ksh88 or a ksh88 derived shell.
>

Ignoring Solaris? It's a pretty widely used commercial Unix,
which happens to have Bourne as /bin/sh (and /sbin/sh).

-Greg
--
::::::::::::: Greg Andrews ::::: ge...@panix.com :::::::::::::
I have a map of the United States that's actual size.
-- Steven Wright

Stephane CHAZELAS

unread,
Jun 27, 2003, 6:15:43 PM6/27/03
to
Greg Andrews wrote:
[...]

> Ignoring Solaris? It's a pretty widely used commercial Unix,
> which happens to have Bourne as /bin/sh (and /sbin/sh).
[...]

Yes. It's part of the "very few" I was talking about, this was
already reported by Kenny. Solaris seems not to want to comply
to POSIX (also look at its 81's awk).

I guess POSIX shell is in /usr/xpg4/bin/sh, just as POSIX awk is
in /usr/xpg4/bin/awk

Is it always the case in Solaris 9 ?

--
Stéphane

Chris Mattern

unread,
Jun 27, 2003, 6:20:02 PM6/27/03
to
llewelly wrote:
>
> There are two reasons to use the bourne shell:
>
> (a) It is availible on every unix. (except unix <= v6)
>
> (b) On most unices, it is used to write system scripts. (Linux is
> the only exception I can think of offhand - and it uses
> bash.)

In AIX, all the system scripts are written in Korn shell, as a matter of
fact. And true Bourne shell is NOT part of the standard install in AIX;
/usr/bin/sh is just a hardlink to /usr/bin/ksh, and you get an invocation
of Korn shell that runs in a Bourne shell compatibility mode.

Chris Mattern

Stephane CHAZELAS

unread,
Jun 27, 2003, 6:40:45 PM6/27/03
to
Kenny McCormack wrote:
[...]

> I think my point is that I'd rather ash *not* be
> POSIX - since the whole point of ash is to be small.

I think the point was to provide a public domain
reimplementation of the System V shell.

It was very useful to BSD guys to avoid copyright conflicts with
Bell labs about the Bourne shell (anyway, I was far too young at
that time (1989), that's just things I read).

Note that ash is a nightmare for one who wants to identify a
shell. First, in the original ash, the set of builtin commands
is chosen at compile time, and then, as I said, many
modifications were made on it by different persons.

Note that it is not much less featured than POSIX shells. I
think that debian or BSD guys chose it as a basis for their
POSIX shell, just because it was not a too far from a POSIX
shell (at least not with too many extensions).

To check if your sh is ash based, you may try:

case `exec 2> /dev/null
setvar _foo_ _foo_; ( echo ${_foo_?_foo_} )2>&1
` in
_foo_) echo ash like;;
*) echo not ash like;;
esac

--
Stéphane

Stephane CHAZELAS

unread,
Jun 27, 2003, 6:45:01 PM6/27/03
to
Chris Mattern wrote:
[...]

> In AIX, all the system scripts are written in Korn shell, as a matter of
> fact. And true Bourne shell is NOT part of the standard install in AIX;
> /usr/bin/sh is just a hardlink to /usr/bin/ksh, and you get an invocation
> of Korn shell that runs in a Bourne shell compatibility mode.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

What makes you say so?

--
Stéphane

Stephane CHAZELAS

unread,
Jun 28, 2003, 9:49:27 AM6/28/03
to
Stephane CHAZELAS wrote:
[...]

> 10- no way to do word splitting on spaces so that empty elements are
> allowed. Because SPC, TAB, NL are /IFS white space characters/
[...]

Oops. Actually, ksh93 has IFS=" " (two consecutive spaces) for
that, just as zsh.

--
Stéphane

Heiner Steven

unread,
Jun 30, 2003, 5:05:48 PM6/30/03
to
Stephane CHAZELAS wrote:
> Greg Andrews wrote:
> [...]
>
>>Ignoring Solaris? It's a pretty widely used commercial Unix,
>>which happens to have Bourne as /bin/sh (and /sbin/sh).
>
> [...]
>
> Yes. It's part of the "very few" I was talking about, this was
> already reported by Kenny. Solaris seems not to want to comply
> to POSIX (also look at its 81's awk).

The POSIX standard doesn't say that a POSIX shell has to be named
/bin/sh, and therefore /bin/sh does not have to
be a POSIX shell (with ksh88 features).

With Solaris 9 you get

/bin/sh # Bourne shell
/bin/ksh # ksh88
/usr/xpg4/bin/sh # POSIX shell
/usr/dt/bin/dtksh # ksh93 (M-12/27/93d)

instead.

Things like /bin/awk being a very old AWK implementation
(and having to use /bin/nawk instead) are caused by Sun
taking backward compatibility very seriously.

If Solaris only would support ksh93, so I could use
associative arrays in my scripts...

Heiner
--
___ _
/ __| |_ _____ _____ _ _ Heiner STEVEN <heiner...@nexgo.de>
\__ \ _/ -_) V / -_) ' \ Shell Script Programmers: visit
|___/\__\___|\_/\___|_||_| http://www.shelldorado.com/

j...@invalid.address

unread,
Jun 30, 2003, 5:30:40 PM6/30/03
to
Heiner Steven <heiner...@nexgo.de> writes:

> If Solaris only would support ksh93, so I could use
> associative arrays in my scripts...

You can use associative arrays in your scripts. Just write them in
perl :-)

Joe

Chris F.A. Johnson

unread,
Jul 1, 2003, 12:58:11 AM7/1/03
to

Why go to the expense of perl when awk has associative arrays?

And they can be emulated to a great degree even in a Bourne shell.

--
Chris F.A. Johnson http://cfaj.freeshell.org
===================================================================
My code (if any) in this post is copyright 2003, Chris F.A. Johnson
and may be copied under the terms of the GNU General Public License

j...@invalid.address

unread,
Jul 1, 2003, 9:06:44 AM7/1/03
to
"Chris F.A. Johnson" <c.f.a....@rogers.com> writes:

> On Mon, 30 Jun 2003 at 21:30 GMT, j...@invalid.address wrote:
> > Heiner Steven <heiner...@nexgo.de> writes:
> >
> >> If Solaris only would support ksh93, so I could use
> >> associative arrays in my scripts...
> >
> > You can use associative arrays in your scripts. Just write them in
> > perl :-)
>
> Why go to the expense of perl when awk has associative arrays?

Lots of things you can't do in awk that you can in perl.

Kenny McCormack

unread,
Jul 1, 2003, 11:12:16 AM7/1/03
to
In article <m3znjyz...@invalid.address>, <j...@invalid.address> wrote:
...
>> > You can use associative arrays in your scripts. Just write them in
>> > perl :-)
>>
>> Why go to the expense of perl when awk has associative arrays?
>
>Lots of things you can't do in awk that you can in perl.

Lots of things you can do in assembler that you can't do in perl.

j...@invalid.address

unread,
Jul 1, 2003, 11:35:57 AM7/1/03
to
gaz...@yin.interaccess.com (Kenny McCormack) writes:

Well, gee, why stop there? If you want to be unrealistic about it,
there's always binary opcodes written directly into an ELF file with a
hex editor.

I was only joking in my comment to Heiner in the first place (notice
the smiley). However, if you want associative arrays, and you need to
do things that awk doesn't do, I don't see why perl is such a bad
choice. It's certainly not comparable to using assembler.

Dan Mercer

unread,
Jul 1, 2003, 11:59:55 AM7/1/03
to

<j...@invalid.address> wrote in message news:m3vfumz...@invalid.address...

No, you can learn to use assembler competently relatively quickly (;-)

Dan Mercer
dme...@mn.rr.com

:


j...@invalid.address

unread,
Jul 1, 2003, 12:33:15 PM7/1/03
to
"Dan Mercer" <dme...@mn.rr.com> writes:

Well, maybe it really is all relative :-)

Joe

Kenny McCormack

unread,
Jul 1, 2003, 12:32:28 PM7/1/03
to
In article <%diMa.161802$Xl.25...@twister.rdc-kc.rr.com>,

Dan Mercer <dme...@mn.rr.com> wrote:
>...
>: > >> > You can use associative arrays in your scripts. Just write them in
>: > >> > perl :-)
>: > >>
>: > >> Why go to the expense of perl when awk has associative arrays?
>: > >
>: > >Lots of things you can't do in awk that you can in perl.
>: >
>: > Lots of things you can do in assembler that you can't do in perl.
>:
>: Well, gee, why stop there? If you want to be unrealistic about it,
>: there's always binary opcodes written directly into an ELF file with a
>: hex editor.
>:
>: I was only joking in my comment to Heiner in the first place (notice
>: the smiley). However, if you want associative arrays, and you need to
>: do things that awk doesn't do, I don't see why perl is such a bad
>: choice. It's certainly not comparable to using assembler.
>
>No, you can learn to use assembler competently relatively quickly (;-)

Yes, I was about to point out that assembler is more logical and has less
weird syntax and fewer gotchas. And, yes, like AWK, KSH(93), and Perl, you
can do associative arrays in it.

Stephane CHAZELAS

unread,
Jul 1, 2003, 1:01:30 PM7/1/03
to
Heiner Steven wrote:
[...]
>> Yes. It's part of the "very few" I was talking about, this was
>> already reported by Kenny. Solaris seems not to want to comply
>> to POSIX (also look at its 81's awk).
>
> The POSIX standard doesn't say that a POSIX shell has to be named
> /bin/sh, and therefore /bin/sh does not have to
> be a POSIX shell (with ksh88 features).
[...]

But what's the use of a standard if we can't write scripts
portably with it.

POSIX says:

Applications should note that the standard PATH to the shell
cannot be assumed to be either /bin/sh or /usr/bin/sh, and
should be determined by interrogation of the PATH returned
by getconf PATH , ensuring that the returned pathname is an
absolute pathname and not a shell built-in.

So what's the way to write a portable POSIX shell script?
What would the shebang line be (/bin/sh assuming a Bourne like
shell and find out the PATH of the POSIX shell in a preamble?)?
What's the path of the POSIX "getconf" utility?

Does "getconf PATH" return /usr/xpg4/bin before /bin on Solaris?

--
Stéphane

Chet Ramey

unread,
Jul 1, 2003, 3:39:10 PM7/1/03
to
In article <slrnbg3fc3.40.s...@pcchazelas.free.fr>,
Stephane CHAZELAS <stephane...@yahoo.fr> wrote:

>So what's the way to write a portable POSIX shell script?

There used to be a suggested preamble in the POSIX.2 rationale.
I don't know if it made it to the web.

>What would the shebang line be (/bin/sh assuming a Bourne like
>shell and find out the PATH of the POSIX shell in a preamble?)?

POSIX doesn't assume that such a facility exists. There's only
one POSIX shell.

>What's the path of the POSIX "getconf" utility?

getconf=$(command -p getconf)

Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
( ``Discere est Dolere'' -- chet )

Chet Ramey, ITS, CWRU ch...@po.CWRU.Edu http://cnswww.cns.cwru.edu/~chet/

Heiner Steven

unread,
Jul 1, 2003, 4:40:30 PM7/1/03
to
Stephane CHAZELAS wrote:
> Heiner Steven wrote:
> [...]
>
>>>Yes. It's part of the "very few" I was talking about, this was
>>>already reported by Kenny. Solaris seems not to want to comply
>>>to POSIX (also look at its 81's awk).
>>
>>The POSIX standard doesn't say that a POSIX shell has to be named
>>/bin/sh, and therefore /bin/sh does not have to
>>be a POSIX shell (with ksh88 features).
>
> [...]
>
> But what's the use of a standard if we can't write scripts
> portably with it.
>
> POSIX says:
>
> Applications should note that the standard PATH to the shell
> cannot be assumed to be either /bin/sh or /usr/bin/sh, and
> should be determined by interrogation of the PATH returned
> by getconf PATH , ensuring that the returned pathname is an
> absolute pathname and not a shell built-in.

This paragraph talks about applications. It could mean
applications that use a shell internally should find the path of
a POSIX shell. Examples: applications with an own version of "system",
or that use the shell for globbing, or just provide a way to
"shell out" of the program (e.g. by accepting a "!command" sequence,
as "vi" does).

> So what's the way to write a portable POSIX shell script?

I'd say that the question is not how to write a portable
POSIX shell script (because the answer is: by only using
shell constructs and external commands defined by POSIX),
but better "how to ensure that POSIX scripts are always
interpreted by a POSIX shell".

> What would the shebang line be (/bin/sh assuming a Bourne like
> shell and find out the PATH of the POSIX shell in a preamble?)?

I fear the answer is, that the scripts have to depend on a
system administrator of user to have set up his earch PATH
correctly. Nevertheless, the "find the right shell" preamble
is a good idea. I always use it for perl scripts:

# The following two lines invoke the perl interpreter if this
# script was executed by some shell
eval 'exec perl -S $0 ${1+"$@"}'
if $running_unser_some_shell;

[The lines were taken from some Perl book]

> What's the path of the POSIX "getconf" utility?

Again an application/script should probably rely on the
PATH being correct:

[Linux]
$ type getconf
getconf is /usr/bin/getconf
$ ksh93
$ type getconf
getconf is a shell builtin

> Does "getconf PATH" return /usr/xpg4/bin before /bin on Solaris?

Yes, it does:

[Solaris 9]
$ getconf PATH
/usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin

[Linux]
$ getconf PATH
/bin:/usr/bin

Stephane CHAZELAS

unread,
Jul 2, 2003, 4:23:28 AM7/2/03
to
Chet Ramey wrote:
> In article <slrnbg3fc3.40.s...@pcchazelas.free.fr>,
> Stephane CHAZELAS <stephane...@yahoo.fr> wrote:
>
>>So what's the way to write a portable POSIX shell script?
>
> There used to be a suggested preamble in the POSIX.2 rationale.
> I don't know if it made it to the web.

I could not find it.

[...]


>>What's the path of the POSIX "getconf" utility?
>
> getconf=$(command -p getconf)

Yes, but that's a POSIX construct, it can't be put in a
non-POSIX preamble.

Here, we'd need at least one POSIX absolute path to resolve
the path of sh. The simplest would have been the path to
the POSIX sh utility itself.

--
Stéphane

Stephane CHAZELAS

unread,
Jul 2, 2003, 4:23:29 AM7/2/03
to
Heiner Steven wrote:
[...]

> eval 'exec perl -S $0 ${1+"$@"}'
> if $running_unser_some_shell;
>
> [The lines were taken from some Perl book]
[...]

Should be:

eval 'exec perl -S "$0" ${1+"$@"}'
if $running_unser_some_shell;

Note it won't work correctly if run by zsh in sh or ksh
emulation...

eval 'exec perl -S "$0" "$@"'
if $running_unser_some_shell;

would, but not in some bourne shells.

eval "exec perl -S \"\$0\" ${1+\"\$@\"}"
if $running_unser_some_shell;

might work for both.

--
Stéphane

lvi...@yahoo.com

unread,
Jul 7, 2003, 6:58:53 AM7/7/03
to

:eval "exec perl -S \"\$0\" ${1+\"\$@\"}"

: if $running_unser_some_shell;
:
:might work for both.

Would things run any better if the if tested the right variable?

:eval "exec perl -S \"\$0\" ${1+\"\$@\"}"
: if $running_under_some_shell;
--
The Tenth Annual Tcl/Tk Conference <URL: http://www.tcl.tk/community/tcl2003 >
Even if explicitly stated to the contrary, nothing in this posting
should be construed as representing my employer's opinions.
<URL: mailto:lvi...@yahoo.com > <URL: http://www.purl.org/NET/lvirden/ >

Stephane CHAZELAS

unread,
Jul 7, 2003, 7:51:57 AM7/7/03
to
lvi...@yahoo.com wrote:
>
>:eval "exec perl -S \"\$0\" ${1+\"\$@\"}"
>: if $running_unser_some_shell;
>:
>:might work for both.
>
> Would things run any better if the if tested the right variable?
>
>:eval "exec perl -S \"\$0\" ${1+\"\$@\"}"
>: if $running_under_some_shell;


Not really. Every variable name is OK as long as it doesn't
exist. To improve it a bit, we could use

q= IFS=, q=; eval "exec perl -S \"\$0\" ${1+\"\$@\"}"
= if $running_under_some_shell;

So that it works with very old Bourne shells even when a
problematic IFS is taken from the environment.

It seems to work with UV7 shell. Next step is to port perl to
that system.

--
Stéphane

Rick Hohensee

unread,
Mar 8, 2021, 8:17:16 AM3/8/21
to
On Sunday, June 22, 2003 at 12:06:42 PM UTC-4, TAM wrote:
> Hi,
> I was wondering if there is any program (e.g. Cygwin) that will allow me to
> do learn Bourne shell programming on Windows 2000 Pro.
> Thanx

If you want to program windows use vb or something. If you want to learn a unix shell get a shell app for your phone. Termux on Android is basically debian linux.

Oğuz

unread,
Mar 8, 2021, 11:08:26 AM3/8/21
to
Not really. Termux doesn't support C locale, it sucks

Kaz Kylheku

unread,
Mar 8, 2021, 12:37:09 PM3/8/21
to
Termux is based on the Android Bionic C library, which is a significant
difference from Debian GNU/Linux.

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

Kaz Kylheku

unread,
Mar 8, 2021, 12:39:24 PM3/8/21
to
Are you saying that a C program running on Bionic is localized (for
example, as if by a call to setlocale(LC_ALL, "")) even if it made no
such call, and so is never in the default "C" locale?

If so, do you have convenient a reference for this, before I go digging?

Jorgen Grahn

unread,
Mar 8, 2021, 2:49:14 PM3/8/21
to
The OP is back in 2003; he/she doesn't have an Android phone. Not
VirtualBox either: it won't become available until 2007.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Keith Thompson

unread,
Mar 8, 2021, 6:56:16 PM3/8/21
to
You're replying to a post from 2003. The OP very likely isn't on
Usenet anymore.

Cygwin is a good way to do shell programming under Windows. I use it
myself. There are other Unix-like environments for Windows as well
(more than were available in 2003). PowerShell is a more native
environment for Windows; there's even a Linux port.

Termux on Android gives you a Debian-like environment, similar
in many ways to the environment Cygwin gives you under Windows.
(There are significant differences.) Doing shell programming
is going to be painful unless you ssh into the phone (which you
can do with Cygwin) -- or you could use a Bluetooth keyboard, but
the display is going to feel cramped. Due to some recent changes,
you'll probably want to install Termux via F-Droid rather than from
Google Play.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

Oğuz

unread,
Mar 21, 2021, 5:58:01 AM3/21/21
to
On Monday, March 8, 2021 at 8:39:24 PM UTC+3, Kaz Kylheku wrote:
> On 2021-03-08, Oğuz <oguzism...@gmail.com> wrote:
> > On Monday, March 8, 2021 at 4:17:16 PM UTC+3, Rick Hohensee wrote:
> >> On Sunday, June 22, 2003 at 12:06:42 PM UTC-4, TAM wrote:
> >> > Hi,
> >> > I was wondering if there is any program (e.g. Cygwin) that will allow me to
> >> > do learn Bourne shell programming on Windows 2000 Pro.
> >> > Thanx
> >>
> >> If you want to program windows use vb or something. If you want to learn a unix shell get a shell app for your phone. Termux on Android is basically debian linux.
> >
> > Not really. Termux doesn't support C locale, it sucks
> Are you saying that a C program running on Bionic is localized (for
> example, as if by a call to setlocale(LC_ALL, "")) even if it made no
> such call, and so is never in the default "C" locale?

I'm saying setting `LC_ALL' to `C' doesn't have any discernible effect on programs that rely on `MB_CUR_MAX' symbol to tell whether a character can be multiple bytes long or not if such programs are compiled for/on Termux. For example:

$ LC_ALL=C
$ case ğ in [ğ-ğ]) echo match; esac
match
$ awk '{print length}' <<<ğ
1

Janis Papanagnou

unread,
Mar 21, 2021, 8:28:23 AM3/21/21
to
On 21.03.2021 10:57, Oğuz wrote:
>
> I'm saying setting `LC_ALL' to `C' doesn't have any discernible
> effect on programs that rely on `MB_CUR_MAX' symbol to tell whether a
> character can be multiple bytes long or not if such programs are
> compiled for/on Termux. For example:
>
> $ LC_ALL=C
> $ case ğ in [ğ-ğ]) echo match; esac
> match
> $ awk '{print length}' <<<ğ
> 1

$ awk '{print length($0)}' <<< "ğ"
1
$ LC_ALL=C awk '{print length($0)}' <<< "ğ"
2

$ awk 'BEGIN{print length("ß")}'
1
$ LC_ALL=C awk 'BEGIN{print length("ß")}'
2


Janis

Oğuz

unread,
Mar 21, 2021, 8:30:13 AM3/21/21
to
Now run these on Termux

>
>
> Janis

Keith Thompson

unread,
Mar 21, 2021, 4:37:02 PM3/21/21
to
You should export LC_ALL in case it's not already in the environment.
With that change, here's a test script:

#!/bin/bash

export LC_ALL=C
case ğ in
[ğ-ğ]) echo -n "match " ;;
*) echo -n "no match " ;;
esac
awk '{print length}' <<< "ğ"

On Ubuntu, the output is "no match 2".
On Termux, the output is "match 1".
0 new messages