KSH tips and tricks
Various Shell Prompt Tips
C-U
- Clear the prompt line
Add prompt editing using VISUAL
. TBD.
.profile
.
Customization of shell prompt. Add the following to Make shell prompt more informative
HOST=`hostname`
export PS1='${USER}@${HOST%%.*} ${PWD##*/} # '
push and pop directories
pushd
and popd
is really useful when working in the command prompt. pushd <dir>
push current directory on a directory stack and change currend directory to <dir>
. popd
change current directory to the laste pushed directory on stack.
cd /home/peter
pushd /root
popd
pushd
and popd
is part of csh
but not in ksh
.
In ksh
you may use cd -
and cd --
to go back 1 and 2 folders in history. This also works in csh
.
cd /home/peter
cd /root
cd -
Command substitution
Command subtitution is performed by $( )
or ` `
notation. The first is recommended for compatibility reasons.
One thing to note abount ksh
is that it removes all trailing newline characters when performing command substitution. See following example.
# echo $(ls)
file1 file2 file3
To preserve newline characters you can the substituted command in " "
.
# echo "$(ls)"
file1
file2
file3
See Command substitution in the Korn shell or POSIX shell for more information.
String Operators
Operator Substitution
${ varname :- word }
If varname exists and isn't null, return its value; otherwise return word.
Purpose: Returning a default value if the variable is undefined.
Example:
${count:-0} evaluates to 0 if count is undefined.
${ varname := word}
If varname exists and isn't null, return its value; otherwise set it to word and then return its value.[7]
Purpose: Setting a variable to a default value if it is undefined.
Example:
$ {count:=0} sets count to 0 if it is undefined.
${ varname :? message }
If varname exists and isn't null, return its value; otherwise print varname : followed by message , and abort the current command or script. Omitting message produces the default message parameter null or not set .
Purpose: Catching errors that result from variables being undefined.
Example:
{count :?" undefined! " } prints "count: undefined!" and exits if count is undefined.
${ varname :+ word }
If varname exists and isn't null, return word ; otherwise return null.
Purpose: Testing for the existence of a variable.
Example:
${count:+1} returns 1 (which could mean "true") if count is defined.
See Learning the Korn Shell - Ch 4.
Editing mode
ksh
can (as other shells) work in either emacs
(default) or vi
mode. Some commonly used commands for emacs
mode are.
CTRL-A Move to beginning of line
CTRL-E Move to end of line
CTRL-K Delete ("kill") forward to end of line
CTRL-W Delete ("kill") one word backwards
ESC-B Move one word back (ALT-RIGHT also works on Mac)
ESC-F Move one word forward (ALT-LEFT alsto works on Mac)
See Emacs Edit Mode.
If you want to switch to vi
editing mode simply do.
set -o vi
set -o emacs # go back to emacs mode
Some useful vi editing commands
ESC escape to command mode
i enter insert mode (initial mode)
w Move one work forward (command mode)
b Move one work backwards (command mode)
cw Remove current word and enter insert mode (command mode)
Diffuculties with sub-shells
See 8.6 Subshells in Learning the Kort Shell for an overview.
The problem is that it can be difficult to know when a code block is run in a sub-shell or not. Some implementations differ as well. One difference between code blocks and code blocks run in a sub-shell doesn't is that sub-shells doesn't inherit shell variables to (and from) the parent shell. See the following example. Also see while read loop scope variables for an explanation.
#!/bin/ksh
# Here the while code block is run in the parent shell
IFS=','
while read a b c ; do
pa=$a
pb=$b
echo "$a,$b"
done << EOF
`echo "a,b"`
EOF
echo $a # These are empty as last line is EOF
echo $b
echo $pa # These are printed
echo $pb
# While this variant seems to create a sub-shell where env. variables are not accessible
echo "a,b" | while read d e f ; do
pd=$d
pe=$e
echo "$d;$e"
done
echo $d # None of these are set due inaccessible env. variables
echo $e
echo $pd
echo $pe
This is just one of the strange things that may happen in shell scripts.
awk
Proper escaping with See the folloing functions that print column n specified in $1
from a ;
separated string specified in $2
. awk
want the command to be enclosed in single quotes ('
), but that also means that ksh
will leave that string un-evaluated. The solution is to enclose the complete awk
command in a double quote string ("
) and evaluate it using eval
command. The $1
string will be evaluated to the column number (e.g. "2") so the resulting awk command will be awk -F'[;]' '{ print $2 }'
. The dollar sign must be escaped when inside double quotes to disable ksh variable substitution for those.
# Print column n (1..) in $1 from string in $2 with ; as separator
col() {
# eval is used to expand $1
echo "$2" | eval "awk -F'[;]' '{ print \$"$1" }'"
}
Command history (in ksh)
ksh does support command history just as e.g. bash does. Command history is stored by default in $HOME/.sh_history
. But a custom history file can be used by setting HISTFILE
environment variable.
History can be shown using fc
(in ksh) and/or history
(in csh). In ksh history is usually aliased to fc -l
. Default fc editor is ed
but can be changed with FCEDIT
environment variable.
fc -l # or history
fc -e - ls # call last ls command
- Korn shell or POSIX shell command history
- Unix fc and history command
- Korn Shell Programming Ref Card
- UNIX Ref Card