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.
It's showing the contents of the special variable $@
, in Bash. It contains all the command line arguments, and this command is taking all the arguments from the second one on and storing them in a variable, variable
.
Example
Here's an exampe script.
#!/bin/bash
echo ${@:2}
variable=${@:3}
echo $variable
Example run:
./ex.bash 1 2 3 4 5
2 3 4 5
3 4 5
References
Best Answer
The "and a minimum number of flags" refers to flags set in the hashbang line. They'd be read when the script is started as
./somescript
, and the kernel reads the hashbang line, building a new argument list from the path and options found there. But this does not happen if the script is started asbash somescript
, as the kernel is asked to runbash
, and not the script itself. The shell itself sees the line as a comment to be ignored when eventually reading the script.For example, try the following script (in
./hello
):And run it in both of the two ways:
The extra trace output from
-x
is shown only in the first case, the flag is ignored with the second invocation.Enabling the flag explicitly with a
set
command would make it work the same either way:(though note that if you ever try this with
perl
, it does interpret the hashbang line itself, too.)