If you are using the defaults for bash and zsh:
$ cat ~/.histfile >> ~/.bash_history
$ youreditor ~/.zshrc
# Here change your config to:
HISTFILE=~/.bash_history
$ rm ~/.histfile
Now you have the same file for history in both shells.
Your question is a bit rambling. I'll answer what seems to be the central part, on the difference between ksh and bash that you observe.
You have encountered what is probably the #1 incompatibility between ksh and bash when it comes to scripts. ATT ksh (both ksh88 and ksh93) and zsh execute the last (rightmost) command in a pipeline in the parent shell, whereas other shells (Bourne, ash, bash, pdksh, mksh) execute all the commands including the last one in a subshell.
Here is a simple test program:
msg="a subshell"
true | msg="the parent shell"
echo "This shell runs the last command of a pipeline in $msg"
In ATT ksh and zsh, the second assignment to msg
is executed in the parent shell so the effect is visible after the pipeline. In other shells, this assignment is executed in a subshell so the first assignment remains in place in the parent.
A workaround is to execute the rest of the script in the pipeline. This is a common idiom for reading data and doing some processing afterward:
output_some_stuff | {
var=
while IFS= read -r line; do
var=$(process "$line")
done
use "$var"
}
You appear to have run into a ksh bug. I recommend upgrading to a non-buggy version. If that isn't possible, try Stephane Chazelas's workaround. While you can try running your scripts in bash, it is not (and does not pretend to be) a drop-in replacement for ksh; there are plenty of ksh features that bash doesn't have (and vice versa). Bash and ksh are only compatible in their POSIX core and some other central features (in particular arrays, [[ … ]]
, and local variables in functions declared by typeset
).
You could also try zsh, which when invoked as ksh
behaves in a way that's a bit closer to ksh than bash is. You may nonetheless run into incompatibilities.
Best Answer
[ "$1" = "" ]
and[ -z "$1" ]
are exactly equivalent in bash and other POSIX-compliant shells. (Note that there must be a space on each side of the brackets, unless there is a non-word-constituent character like;
.)[
is a shell built-in like any other; in fact it can also be spelledtest
(the only difference between the two is that[
requires a]
as the last argument). So if you run[ "$1" = "" ]
with$1
expanding to-z
, the test operator sees three arguments:-z
,=
and the empty string. Some older Bourne shells sometimes threw parse errors when an operand looked like an operator in this way, even if there was no ambiguity in the complete expression. I don't know if any version did in fact have trouble with this particular expression, but more complex expressions could throw them off. There may also have been versions that had trouble with empty words; these would not have supported[ -z "$1" ]
either. A common shell idiom is[ x"$1" = x"" ]
. It avoids any risk of having operands parsed as operators because no operator starts with a letter.In ksh, bash and zsh, you can use the double bracket syntax,
[[ -z $1 ]]
. This newer syntax (it's from the late 1980s rather than the mid-1970s) eliminates the risk of having operands parsed as operators by using a special syntactic construct rather than an ordinary built-in. Operators must appear literally, unquoted within the double brackets, and you don't need to double quote variable expansions.