Builtin Commands in Unix - linux

In Unix or Unix like systems, The command is in the type of "shell builtin". The commands like cd, echo are shell builtin. Is there any way
to list all the shell builtin commands or Is there any command available to list all the builtin command of the shell ?

Look up the man page for your shell.
There should be a section "SHELL BUILTIN COMMANDS"
$ man bash

It depends upon the shell. So read the documentation of your particular shell.
For bash, see here.
For zsh, see here.
For fish, see this.
For tcsh(which I don't recommend, STFW for csh considered harmful), see here.
For the POSIX shell specification, read that. If you want to code somehow "portable" shell scripts, you should restrict yourself to that specification.
Some rescue shells have many builtins, to be useful on a severely corrupted or broken system which e.g. has no more any /bin/mv or /bin/cp executables. For example sash.
Some shells are able to load plugins (somehow possibly defining new builtins), or to define functions.
Some shells have a restricted form, which removes some builtins (notably cd). For restricted bash see here.

TAB shows the available commands, from PATH and builtins.
Reset your PATH and enter [TAB] twice and answer y
$ PATH=
$ [TAB][TAB]
Display all 123 possibilities? (y or n)
- compgen fg _ooexp_ spwd
: complete fi path startx
! compopt for _pkcon _strip
. _compreply_ function __pkconcomp suspend
.. continue _gdb_ _pkcon_search test
... coproc getopts popd then
[ __dbus_send hash ppwd time
[[ declare help printf times
]] dir history pushd trap
{ dirs if pwd true
} disown in rd type
+ do jobs read typeset
alias done kill readarray ulimit
beep echo l readonly umask
bg elif la rehash unalias
bind else let remount unmount
break enable ll return unset
builtin esac local _scout until
caller eval logout _scpm wait
case exec ls select while
cd exit ls-l set _yast2
_cd_ _exp_ _man_ shift you
cd.. export mapfile shopt _zypper
command false md skipthis
command_not_found_handle fc o source

just type help on the shell, and a list will appear

Related

Shell script hangs when i switch to bash - Linux [duplicate]

This question already has answers here:
Pass commands as input to another command (su, ssh, sh, etc)
(3 answers)
Closed 6 years ago.
I'm very very new to Linux(coming from windows) and trying to write a script that i can hopefully execute over multiple systems. I tried to use Python for this but fount it hard too. Here is what i have so far:
cd /bin
bash
source compilervars.sh intel64
cd ~
exit #exit bash
file= "~/a.out"
if[! -f "$file"]
then
icc code.c
fi
#run some commands here...
The script hangs in the second line (bash). I'm not sure how to fix that or if I'm doing it wrong. Please advice.
Also, any tips of how to run this script over multiple systems on the same network?
Thanks a lot.
What I believe you'd want to do:
#!/bin/bash
source /bin/compilervars.sh intel64
file="$HOME/a.out"
if [ ! -f "$file" ]; then
icc code.c
fi
You would put this in a file and make it executable with chmod +x myscript. Then you would run it with ./myscript. Alternatively, you could just run it with bash myscript.
Your script makes little sense. The second line will open a new bash session, but it will just sit there until you exit it. Also, changing directories back and forth is very seldom required. To execute a single command in another directory, one usually does
( cd /other/place && mycommand )
The ( ... ) tells the shell that you'd like to do this in a sub-shell. The cd happens within that sub-shell and you don't have to cd back after it's done. If the cd fails, the command will not be run.
For example: You might want to make sure you're in $HOME when you compile the code:
if [ ! -f "$file" ]; then
( cd $HOME && icc code.c )
fi
... or even pick out the directory name from the variable file and use that:
if [ -f "$file" ]; then
( cd $(dirname "$file") && icc code.c )
fi
Assigning to a variable needs to happen as I wrote it, without spaces around the =.
Likewise, there needs to be spaces after if and inside [ ... ] as I wrote it above.
I also tend to use $HOME rather than ~ in scripts as it's more descriptive.
A shell script isn't a record of key strokes which are typed into a terminal. If you write a script like this:
command1
bash
command2
it does not mean that the script will switch to bash, and then execute command2 in the different shell. It means that bash will be run. If there is a controlling terminal, that bash will show you a prompt and wait for a command to be typed in. You will have to type exit to quit that bash. Only then will the original script then continue with command2.
There is no way to switch a script to a different shell halfway through. There are ways to simulate this. A script can re-execute itself using a different shell. In order to do that, the script has to contain logic to detect that it is being re-executed, so that it can prevent re-executing itself again, and to skip some code that shouldn't be run twice.
In this script, I implemented such a re-execution hack. It consists of these lines:
#
# The #!/bin/sh might be some legacy piece of crap,
# not even up to 1990 POSIX.2 spec. So the first step
# is to look for a better shell in some known places
# and re-execute ourselves with that interpreter.
#
if test x$txr_shell = x ; then
for shell in /bin/bash /usr/bin/bash /usr/xpg4/bin/sh ; do
if test -x $shell ; then
txr_shell=$shell
break
fi
done
if test x$txr_shell = x ; then
echo "No known POSIX shell found: falling back on /bin/sh, which may not work"
txr_shell=/bin/sh
fi
export txr_shell
exec $txr_shell $0 ${#+"$#"}
fi
The txr_shell variable (not a standard variable, my invention) is how this logic detects that it's been re-executed. If the variable doesn't exist then this is the original execution. When we re-execute we export txr_shell so the re-executed instance will then have this environment variable.
The variable also holds the path to the shell; that is used later in the script; it is passed through to a Makefile as the SHELL variable, so that make build recipes use that same shell. In the above logic, the contents of txr_shell don't matter; it's used as Boolean: either it exists or it doesn't.
The programming style in the above code snippet is deliberately coded to work on very old shells. That is why test x$txr_shell = x is used instead of the modern syntax [ -z "$txr_shell" ], and why ${#+"$#"} is used instead of just "$#".
This style is no longer used after this point in the script, because the
rest of the script runs in some good, reasonably modern shell thanks to the re-execution trick.

How can I write a bash script that sets a variable that's available to the user in the terminal? [duplicate]

This question already has answers here:
Can I export a variable to the environment from a Bash script without sourcing it?
(13 answers)
Closed 3 years ago.
The community reviewed whether to reopen this question last year and left it closed:
Original close reason(s) were not resolved
I'm trying to write a shell script that, when run, will set some environment variables that will stay set in the caller's shell.
setenv FOO foo
in csh/tcsh, or
export FOO=foo
in sh/bash only set it during the script's execution.
I already know that
source myscript
will run the commands of the script rather than launching a new shell, and that can result in setting the "caller's" environment.
But here's the rub:
I want this script to be callable from either bash or csh. In other words, I want users of either shell to be able to run my script and have their shell's environment changed. So 'source' won't work for me, since a user running csh can't source a bash script, and a user running bash can't source a csh script.
Is there any reasonable solution that doesn't involve having to write and maintain TWO versions on the script?
Use the "dot space script" calling syntax. For example, here's how to do it using the full path to a script:
. /path/to/set_env_vars.sh
And here's how to do it if you're in the same directory as the script:
. set_env_vars.sh
These execute the script under the current shell instead of loading another one (which is what would happen if you did ./set_env_vars.sh). Because it runs in the same shell, the environmental variables you set will be available when it exits.
This is the same thing as calling source set_env_vars.sh, but it's shorter to type and might work in some places where source doesn't.
Your shell process has a copy of the parent's environment and no access to the parent process's environment whatsoever. When your shell process terminates any changes you've made to its environment are lost. Sourcing a script file is the most commonly used method for configuring a shell environment, you may just want to bite the bullet and maintain one for each of the two flavors of shell.
You're not going to be able to modify the caller's shell because it's in a different process context. When child processes inherit your shell's variables, they're
inheriting copies themselves.
One thing you can do is to write a script that emits the correct commands for tcsh
or sh based how it's invoked. If you're script is "setit" then do:
ln -s setit setit-sh
and
ln -s setit setit-csh
Now either directly or in an alias, you do this from sh
eval `setit-sh`
or this from csh
eval `setit-csh`
setit uses $0 to determine its output style.
This is reminescent of how people use to get the TERM environment variable set.
The advantage here is that setit is just written in whichever shell you like as in:
#!/bin/bash
arg0=$0
arg0=${arg0##*/}
for nv in \
NAME1=VALUE1 \
NAME2=VALUE2
do
if [ x$arg0 = xsetit-sh ]; then
echo 'export '$nv' ;'
elif [ x$arg0 = xsetit-csh ]; then
echo 'setenv '${nv%%=*}' '${nv##*=}' ;'
fi
done
with the symbolic links given above, and the eval of the backquoted expression, this has the desired result.
To simplify invocation for csh, tcsh, or similar shells:
alias dosetit 'eval `setit-csh`'
or for sh, bash, and the like:
alias dosetit='eval `setit-sh`'
One nice thing about this is that you only have to maintain the list in one place.
In theory you could even stick the list in a file and put cat nvpairfilename between "in" and "do".
This is pretty much how login shell terminal settings used to be done: a script would output statments to be executed in the login shell. An alias would generally be used to make invocation simple, as in "tset vt100". As mentioned in another answer, there is also similar functionality in the INN UseNet news server.
In my .bash_profile I have :
# No Proxy
function noproxy
{
/usr/local/sbin/noproxy #turn off proxy server
unset http_proxy HTTP_PROXY https_proxy HTTPs_PROXY
}
# Proxy
function setproxy
{
sh /usr/local/sbin/proxyon #turn on proxy server
http_proxy=http://127.0.0.1:8118/
HTTP_PROXY=$http_proxy
https_proxy=$http_proxy
HTTPS_PROXY=$https_proxy
export http_proxy https_proxy HTTP_PROXY HTTPS_PROXY
}
So when I want to disable the proxy,
the function(s) run in the login shell and sets the variables
as expected and wanted.
It's "kind of" possible through using gdb and setenv(3), although I have a hard time recommending actually doing this. (Additionally, i.e. the most recent ubuntu won't actually let you do this without telling the kernel to be more permissive about ptrace, and the same may go for other distros as well).
$ cat setfoo
#! /bin/bash
gdb /proc/${PPID}/exe ${PPID} <<END >/dev/null
call setenv("foo", "bar", 0)
END
$ echo $foo
$ ./setfoo
$ echo $foo
bar
This works — it isn't what I'd use, but it 'works'. Let's create a script teredo to set the environment variable TEREDO_WORMS:
#!/bin/ksh
export TEREDO_WORMS=ukelele
exec $SHELL -i
It will be interpreted by the Korn shell, exports the environment variable, and then replaces itself with a new interactive shell.
Before running this script, we have SHELL set in the environment to the C shell, and the environment variable TEREDO_WORMS is not set:
% env | grep SHELL
SHELL=/bin/csh
% env | grep TEREDO
%
When the script is run, you are in a new shell, another interactive C shell, but the environment variable is set:
% teredo
% env | grep TEREDO
TEREDO_WORMS=ukelele
%
When you exit from this shell, the original shell takes over:
% exit
% env | grep TEREDO
%
The environment variable is not set in the original shell's environment. If you use exec teredo to run the command, then the original interactive shell is replaced by the Korn shell that sets the environment, and then that in turn is replaced by a new interactive C shell:
% exec teredo
% env | grep TEREDO
TEREDO_WORMS=ukelele
%
If you type exit (or Control-D), then your shell exits, probably logging you out of that window, or taking you back to the previous level of shell from where the experiments started.
The same mechanism works for Bash or Korn shell. You may find that the prompt after the exit commands appears in funny places.
Note the discussion in the comments. This is not a solution I would recommend, but it does achieve the stated purpose of a single script to set the environment that works with all shells (that accept the -i option to make an interactive shell). You could also add "$#" after the option to relay any other arguments, which might then make the shell usable as a general 'set environment and execute command' tool. You might want to omit the -i if there are other arguments, leading to:
#!/bin/ksh
export TEREDO_WORMS=ukelele
exec $SHELL "${#-'-i'}"
The "${#-'-i'}" bit means 'if the argument list contains at least one argument, use the original argument list; otherwise, substitute -i for the non-existent arguments'.
You should use modules, see http://modules.sourceforge.net/
EDIT: The modules package has not been updated since 2012 but still works ok for the basics. All the new features, bells and whistles happen in lmod this day (which I like it more): https://www.tacc.utexas.edu/research-development/tacc-projects/lmod
Another workaround that I don't see mentioned is to write the variable value to a file.
I ran into a very similar issue where I wanted to be able to run the last set test (instead of all my tests). My first plan was to write one command for setting the env variable TESTCASE, and then have another command that would use this to run the test. Needless to say that I had the same exact issue as you did.
But then I came up with this simple hack:
First command ( testset ):
#!/bin/bash
if [ $# -eq 1 ]
then
echo $1 > ~/.TESTCASE
echo "TESTCASE has been set to: $1"
else
echo "Come again?"
fi
Second command (testrun ):
#!/bin/bash
TESTCASE=$(cat ~/.TESTCASE)
drush test-run $TESTCASE
You can instruct the child process to print its environment variables (by calling "env"), then loop over the printed environment variables in the parent process and call "export" on those variables.
The following code is based on Capturing output of find . -print0 into a bash array
If the parent shell is the bash, you can use
while IFS= read -r -d $'\0' line; do
export "$line"
done < <(bash -s <<< 'export VARNAME=something; env -0')
echo $VARNAME
If the parent shell is the dash, then read does not provide the -d flag and the code gets more complicated
TMPDIR=$(mktemp -d)
mkfifo $TMPDIR/fifo
(bash -s << "EOF"
export VARNAME=something
while IFS= read -r -d $'\0' line; do
echo $(printf '%q' "$line")
done < <(env -0)
EOF
) > $TMPDIR/fifo &
while read -r line; do export "$(eval echo $line)"; done < $TMPDIR/fifo
rm -r $TMPDIR
echo $VARNAME
Under OS X bash you can do the following:
Create the bash script file to unset the variable
#!/bin/bash
unset http_proxy
Make the file executable
sudo chmod 744 unsetvar
Create alias
alias unsetvar='source /your/path/to/the/script/unsetvar'
It should be ready to use so long you have the folder containing your script file appended to the path.
It's not what I would call outstanding, but this also works if you need to call the script from the shell anyway. It's not a good solution, but for a single static environment variable, it works well enough.
1.) Create a script with a condition that exits either 0 (Successful) or 1 (Not successful)
if [[ $foo == "True" ]]; then
exit 0
else
exit 1
2.) Create an alias that is dependent on the exit code.
alias='myscript.sh && export MyVariable'
You call the alias, which calls the script, which evaluates the condition, which is required to exit zero via the '&&' in order to set the environment variable in the parent shell.
This is flotsam, but it can be useful in a pinch.
You can invoke another one Bash with the different bash_profile.
Also, you can create special bash_profile for using in multi-bashprofile environment.
Remember that you can use functions inside of bashprofile, and that functions will be avialable globally.
for example, "function user { export USER_NAME $1 }" can set variable in runtime, for example: user olegchir && env | grep olegchir
Another option is to use "Environment Modules" (http://modules.sourceforge.net/). This unfortunately introduces a third language into the mix. You define the environment with the language of Tcl, but there are a few handy commands for typical modifications (prepend vs. append vs set). You will also need to have environment modules installed. You can then use module load *XXX* to name the environment you want. The module command is basically a fancy alias for the eval mechanism described above by Thomas Kammeyer. The main advantage here is that you can maintain the environment in one language and rely on "Environment Modules" to translate it to sh, ksh, bash, csh, tcsh, zsh, python (?!?!!), etc.
I created a solution using pipes, eval and signal.
parent() {
if [ -z "$G_EVAL_FD" ]; then
die 1 "Rode primeiro parent_setup no processo pai"
fi
if [ $(ppid) = "$$" ]; then
"$#"
else
kill -SIGUSR1 $$
echo "$#">&$G_EVAL_FD
fi
}
parent_setup() {
G_EVAL_FD=99
tempfile=$(mktemp -u)
mkfifo "$tempfile"
eval "exec $G_EVAL_FD<>'$tempfile'"
rm -f "$tempfile"
trap "read CMD <&$G_EVAL_FD; eval \"\$CMD\"" USR1
}
parent_setup #on parent shell context
( A=1 ); echo $A # prints nothing
( parent A=1 ); echo $A # prints 1
It might work with any command.
I don't see any answer documenting how to work around this problem with cooperating processes. A common pattern with things like ssh-agent is to have the child process print an expression which the parent can eval.
bash$ eval $(shh-agent)
For example, ssh-agent has options to select Csh or Bourne-compatible output syntax.
bash$ ssh-agent
SSH2_AUTH_SOCK=/tmp/ssh-era/ssh2-10690-agent; export SSH2_AUTH_SOCK;
SSH2_AGENT_PID=10691; export SSH2_AGENT_PID;
echo Agent pid 10691;
(This causes the agent to start running, but doesn't allow you to actually use it, unless you now copy-paste this output to your shell prompt.) Compare:
bash$ ssh-agent -c
setenv SSH2_AUTH_SOCK /tmp/ssh-era/ssh2-10751-agent;
setenv SSH2_AGENT_PID 10752;
echo Agent pid 10752;
(As you can see, csh and tcsh uses setenv to set varibles.)
Your own program can do this, too.
bash$ foo=$(makefoo)
Your makefoo script would simply calculate and print the value, and let the caller do whatever they want with it -- assigning it to a variable is a common use case, but probably not something you want to hard-code into the tool which produces the value.
Technically, that is correct -- only 'eval' doesn't fork another shell. However, from the point of view of the application you're trying to run in the modified environment, the difference is nil: the child inherits the environment of its parent, so the (modified) environment is conveyed to all descending processes.
Ipso facto, the changed environment variable 'sticks' -- as long as you are running under the parent program/shell.
If it is absolutely necessary for the environment variable to remain after the parent (Perl or shell) has exited, it is necessary for the parent shell to do the heavy lifting. One method I've seen in the documentation is for the current script to spawn an executable file with the necessary 'export' language, and then trick the parent shell into executing it -- always being cognizant of the fact that you need to preface the command with 'source' if you're trying to leave a non-volatile version of the modified environment behind. A Kluge at best.
The second method is to modify the script that initiates the shell environment (.bashrc or whatever) to contain the modified parameter. This can be dangerous -- if you hose up the initialization script it may make your shell unavailable the next time it tries to launch. There are plenty of tools for modifying the current shell; by affixing the necessary tweaks to the 'launcher' you effectively push those changes forward as well.
Generally not a good idea; if you only need the environment changes for a particular application suite, you'll have to go back and return the shell launch script to its pristine state (using vi or whatever) afterwards.
In short, there are no good (and easy) methods. Presumably this was made difficult to ensure the security of the system was not irrevocably compromised.
The short answer is no, you cannot alter the environment of the parent process, but it seems like what you want is an environment with custom environment variables and the shell that the user has chosen.
So why not simply something like
#!/usr/bin/env bash
FOO=foo $SHELL
Then when you are done with the environment, just exit.
You could always use aliases
alias your_env='source ~/scripts/your_env.sh'
I did this many years ago. If I rememeber correctly, I included an alias in each of .bashrc and .cshrc, with parameters, aliasing the respective forms of setting the environment to a common form.
Then the script that you will source in any of the two shells has a command with that last form, that is suitable aliased in each shell.
If I find the concrete aliases, I will post them.
Other than writings conditionals depending on what $SHELL/$TERM is set to, no. What's wrong with using Perl? It's pretty ubiquitous (I can't think of a single UNIX variant that doesn't have it), and it'll spare you the trouble.

coloring terminal with shell script

Someone can explain me why when I copy and paste the following command in the terminal it displays the colorful test correctly, but when I run it via sh myscript.sh it does not display the colored text?
blue='\e[1;34m'
NC='\e[0m'
echo -e "${blue}Test${NC}"
EDIT
Sudo is not the problem. If I copy the above and paste directly into the terminal, everything works. If you run through file, sh myscript.sh not work
Probably because sh isn't bash on your system.
$ file /bin/sh
/bin/sh: symbolic link to `dash'
Try
bash myscript.sh
Your interactive shell seems to be GNU Bash, while sh is a generic POSIX shell, which actually may be dash, busybox sh or something else. The problem is that neither -e option for echo nor \e are POSIX-compliant.
But you can easily use printf instead of echo -e (do not forget to explicitly specify newline character \n) and \033 instead of \e:
blue='\033[1;34m'
NC='\033[0m'
printf "${blue}%s${NC}\n" 'Test'
Or, of course, you can just use bash (as Elliott Frisch suggested) if you are sure that it would be available on target system.
Also I should point out, that what you done is not right way to run shell scripts at all. If you’re writing a standalone script, then you’d better to use hashbang and set execution bit to file.
$ cat myscript
#!/bin/sh
blue='\033[1;34m'
NC='\033[0m'
printf "${blue}%s${NC}\n" 'Test'
$ chmod +x myscript
$ ./myscript
But if you’re writing a command sequence (a macros, if you will) for interactive shell, there is source (or simply .) command:
$ source myscript
(Then all of above about POSIX-compliance does not matter of course.)

Badly placed ()'s while declaring a function in tcsh

I'm trying to declare a function in tcsh and to call it.
#! /bin/tcsh -f
helloWorld () {
echo "a"
}
helloWorld
I'm getting the following error:
< 512 mews2895 ~/tmp/script> 1.sh
Badly placed ()'s.
Does anyone here what the problem might be?
Thanks
tcsh does not support functions.
Best solution: Use a shell that does, such as bash.
If you must use tcsh for some reason, aliases will solve your immediate problem, but are much weaker than functions.
alias helloWorld 'echo "a"'
Another possible solution is to invoke a separate script. (You'll have to ensure that the invoked script is in your $PATH.)
There are not functions in tcsh. So I see 2 options:
Use aliases:
https://www.ibm.com/support/knowledgecenter/en/SSLTBW_2.2.0/com.ibm.zos.v2r2.bpxa500/alias.htm
Use goto. (People tend to criticize go-to, but It actually depends on the context).
There is an other option, use source if you want to organize your code with multiple files:
To run a shell script in your current environment, without creating a
new process, use the source command. You could run the calculate shell
script this way: source calculate Should you want to use a shell
script that updates a variable in the current environment, run it with
the source command.
src: OS/390 UNIX System Services tcsh (C Shell) Kit Support Guide - IBM
I think that 'use a different shell' should not be a valid response.
Regards,
Pablo
Try below code for functions usage in tcsh
#! /bin/tcsh -f
goto helloWorld
helloWorld:
echo "a"
Although the C Shell lacks functions, aliases serve as workaround. However, pipes and I/O redirection don't work well with multi-line aliases, except if eval is issued. To avoid eval, have the script in a variable and source it from a FIFO:
setenv qscr 'if -e $1 then\
echo OK\
else\
echo Not OK\
endif'
mkfifo ~/qscr
alias qscr '( echo "$qscr:q" > ~/qscr & ) ; source ~/qscr'
Or have it in an alias alone, with echo:
alias qscr '( echo '\''if -e $1 then\\
echo OK\\
else\\
echo Not OK\\
endif'\'' > ~/qscr & ) ; source ~/qscr'
mkfifo ~/qscr

syntax of for loop in linux shell scripting

I have a problem implementing a for loop. I get this error when I execute my script
test1.sh: 2: Syntax error: Bad for loop variable
I don't understand this error.
This is my script
#!/bin/bash
for (( c=1; c<=5; c++ ))
do
echo "Welcome $c times..."
done
can any one tell me syntax for for loop in sh(in ubuntu it links to dash shell) shell in ubuntu?
You probably run it with sh, not bash. Try bash test1.sh, or ./test1.sh if it's executable, but not sh test1.sh.
A standard POSIX shell only accepts the syntax for varname in list
The C-like for-loop syntax for (( expr1; expr2; expr3 )) is a bashism.
You can get similar behavior in the standard POSIX shell using for c in $(seq 1 5)
What does
ls -l /bin/sh
give on your machine ?
Make sh a symbolic link to bash and then you can do sh ./test1.sh
Your shell script (as shown) runs in both Korn shell and Bash. Some thoughts:
You might need a space after the shebang (#! /bin/bash and not #!/bin/bash). However, Dennis Ritchie had originally specified the space is optional. Besides, it isn't the error you get with Bourne shell (you get syntax error: '(' unexpected instead).
Are you on a Windows system? Just a stab in the dark. This doesn't look like a Windows error.
Is this Solaris or HP/UX system? They might not be running true versions of Bash, or maybe an older version. However, even the oldest version of Bash recognizes the for ((x;y;z)) construct.
Try this:
#! /bin/bash
set -vx
echo "Random = $RANDOM" #Test for bash/Kornshell. Will be blank in other shells
echo \$BASH_VERSINFO[0] = ${BASH_VERSINFO[0]} #Should only work in BASH
echo \$BASH_VERSINFO[1] = ${BASH_VERSINFO[1]}
echo \$BASH_VERSINFO[2] = ${BASH_VERSINFO[2]}
echo \$BASH_VERSINFO[3] = ${BASH_VERSINFO[3]}
echo \$BASH_VERSINFO[4] = ${BASH_VERSINFO[4]}
echo \$BASH_VERSINFO[5] = ${BASH_VERSINFO[5]}
for ((c=0, c<=5, c++))
do
echo "Welcome $c times"
done
The set -xv will display all lines as they are executed.
The $RANDOM should display a value if this is either BASH or Kornshell (your for loop will work in either one).
The {$BASH_VERINFO[x]} should only be set if this is truly BASH. These aren't even set even if you run Korn shell after you're in BASH (unlike $SHELL which will still contain bash).
If the for loop still gives you trouble, just delete it. Somewhere in this script, we'll find out if you're really executing a bash shell or not.

Resources