Learning the Korn Shell, 2nd Edition by Bill Rosenblatt, Arnold Robbins The unconfirmed error reports are from readers. They have not yet been approved or disproved by the author or editor and represent solely the opinion of the reader. Here's a key to the markup: [page-number]: serious technical mistake {page-number}: minor technical mistake : important language/formatting problem (page-number): language change or minor formatting problem ?page-number?: reader question or request for clarification This page was updated March 26, 2007. UNCONFIRMED errors and comments from readers: (4) The Korn Shell, 2nd paragraph, 1st sentence; In following part: ... as part of AT&T's "Experimental Toolchest," meaning that ... the quote and the comma must be switched: ... as part of AT&T's "Experimental Toolchest", meaning that ... (22) Background Jobs, first paragraph; Second sentence begins with a lowercase letter and is poorly worded. Current sentence begins: any other commercial operating systems don't have... Recommended change: Other commercial operating systems do not have... (30) Table 1-7; The second sentence of the Function Description for DEL or CTRL-? is: "This is a common alternative setting. for the erase character" Should be: "This is a common alternative setting for the erase character" {74} 10th line from top; The output of print "The value of \$varname is \"$varname\"." (on 6th line) should be The value of $varname is "bob". (80) Terminal types, first paragraph; A space is missing between "like" and "more" on the last line of this paragraph. (97) Last paragraph, first sentence; The sentence reads, "In addition, one other environment variable may be assigned to." This is a sentence fragment. (103) function countargs definition; Taking the called function's results into account, the contents of the function countargs should be: print "$# args" instead of: print "$# args." (114) 2nd line; 2nd line on this page should be: duction may be found in the second edition of ... instead of: duction may found in the second edition of ... (121) Table 4-9, 3rd operator; the operator must be described as: ${variable%pattern} instead of: ${{variable%pattern} {122} Last paragraph but one; There is no difference between using %% or % in this case. The discussion would be true if the example were: objname=${filename%.*}.o instead of: objname=${filename%.c}.o Furthermore, part of the last sentence but one should be (2 differences!): ..., so it would match .tab.c and evaluate to y.o rather than to y.tab.o. instead of: ..., so it would match .tab.o and evaluate to y.o rather than y.tab.o. (128) 2nd paragraph; In the fourth line of the page => 'substituion', should be 'substitution'. (151) line 4; this line should be: the null string isn't a valid directory name, the condition will fail. instead of: the null string isn't a valid directory name, the conditional will fail. (178) topic 5, 2nd line; color must be changed into colon {181} script code, last line but 6; the ;; must be removed after the line as "$filename" "$objname" ;; [190] 190-193; I couldn't get the directory stack system to work as advertised. Here's a variation of the source that does work (this is a section from my .kshrc): # should this be in this file? export DIRSTACK="" # [CHANGE 1/3] THERE IS NO REASON TO # HAVE STACK NON-EMPTY TO START WITH. function dirs { print $DIRSTACK } function getNdirs { stackfront='' let count=0 while (( count < $1 )); do stackfront="$stackfront ${DIRSTACK%% *}" DIRSTACK=${DIRSTACK#* } let count++ done } function pushd { if [[ $1 == ++([0-9]) ]]; then # case of pushd +n: rotate n-th directory to top num=${1#+} getNdirs $num newtop=${stackfront##* } stackfront=${stackfront%$newtop} DIRSTACK="$newtop $stackfront $DIRSTACK" cd $newtop elif [[ -z $1 ]]; then # case of pushd without args; swap top two directories firstdir=${DIRSTACK%% *} DIRSTACK=${DIRSTACK#* } seconddir=${DIRSTACK%% } DIRSTACK=${DIRSTACK#* } DIRSTACK="$seconddir $firstdir $DIRSTACK" cd $seconddir else # normal case of pushd dirname dirname=$1 if [[ -d $dirname && -x $dirname ]]; then bufpwd=$PWD # [CHANGE 2/3]: this is a new line cd $dirname DIRSTACK="$bufpwd $DIRSTACK" # [CHANGE 3/3]: changed #print "$DIRSTACK" else print still in "$PWD." return 1 fi fi } function popd { # pop directory off the stack, cd to new top if [[ $1 == ++([0-9]) ]]; then # case of oppd +n : delete n-th directory from stack num=${1#+} getNdirs $num stackfront=${stackfront% *} DIRSTACK="$stackfront $DIRSTACK" else # normal case of popd without arg if [[ -n $DIRSTACK ]]; then top=${DIRSTACK%% *} DIRSTACK=${DIRSTACK#* } cd $top print "$PWD" else print "stack empty" return 1 fi fi } {191} pushd() and popd() script; The pushd() and popd() work, but are slightly different than the pushd and popd in bash. pushd fix: If DIRSTACK is empty, pushd should push the current dir first. The else clause of the outside if statement should read: if [[ -d $dirname && -x $dirname ]]; then DIRSTACK="$dirname ${DIRSTACK:-$PWD" "}" cd $dirname print "$DIRSTACK" else instead of: if [[ -d $dirname && -x $dirname ]]; then cd $dirname DIRSTACK="$dirname $DIRSTACK" print "$DIRSTACK" else popd fix: In the else clause of the outside if statement should read: # normal case of popd without argument if [[ -n $DIRSTACK ]]; then DIRSTACK=${DIRSTACK#* } cd ${DIRSTACK%% *} print "$PWD" else instead of: # normal case of popd without argument if [[ -n $DIRSTACK ]]; then top=${DIRSTACK%% *} DIRSTACK=${DIRSTACK#* } cd $top print "$PWD" else (211) 3 lines before 'Here-Documents' header; The line should end like this: ... to update data in a file "in place". instead of: ... to update data in a file "in place." (246) 1st paragraph, past the middle; "..., we use the the cleverly named command command to" should be changed into "..., we use the cleverly named command command to" (269) 2nd line; ... concatenating the the results of ... must be changed into ... concatenating the results of ...