Shebang's relation to current shell - shell

If my current shell is a tcsh shell (confirmed with >echo $shell and >ps $$ etc.), do I have to write shebangs like #! bin/tcsh and have only that kind of scripts to run properly?
I made scripts with sh shebangs #! bin/sh and they run properly, although my shell was always a tcsh shell. My scripts had forloops, which are different in sh and tcsh.
Do I need to change my current tcsh shell into sh shell in order to run scripts with sh shebangs?
Any help?
Thanks!

IF your shebang lines were actually #! bin/sh then the reason that they worked correctly is because that path doesn't exist and your current shell is taking over running of the script.
Fix the path in the shebang line to be a valid absolute path #!/bin/sh and I expect you will see the scripts start to fail.
See http://www.in-ulm.de/~mascheck/various/shebang/ for more about the shebang line that you likely care about.

Related

bash scripting: sourcing tcsh script

I need to source a tcsh script from my bash script. I have tried to do it like this:
tcsh -c "source ~/test.tcsh"
The problem with this command is that $_ is empty inside of the sourced tcsh script. Any ways to deal with that?
Thanks in advance!
The source command runs the script in the current shell. tcsh -c "source ~/test.tcsh" sources the file test.tcsh in the shell running the source command, which is an instance of tcsh, not the bash shell that runs tcsh. You aren't going to be able to execute a tcsh script in any way that affects the environment of the current bash shell. You could start a new bash shell that inherits from an instance of tcsh which was so modified, with something like
tcsh -c 'source ~/test.tcsh; bash'
but that may not be what you need. For instance,
tcsh -c 'source ~/test.tcsh; bash'
echo "OK, we're back"
will leave you in an interactive bash shell, but you won't see "OK, we're back" until after you exit that shell, which will cause tcsh to exit and return control to the original.

Why does this sh shebang not work?

In the following script (saved as script.sh):
#!/bin/sh
cd $MY_PYTHON_WORKING_DIRECTORY
python script1.py
python script2.py
Then, when I try to run the command script.sh in my bash shell, I got the error bash: script.sh: command not found. Why does this not work as expected? If the first line of any scripts start by #! prefix, then the following path on the line is interpreted as a command, right? For your information, even if I changed my first line to #!/bin/bash, the same error still occurred. If I run the script as either sh script.sh or bash script.sh, then the script ran as expected.
Is there any way to run the script by just hitting script.sh?
One more question, between sh and bash, which should I use? I'm on OS X 10.8 and my default shell is currently set bash, but I wonder which one to use going forward.
Thanks.
First, make the script executable:
chmod u+x script.sh
Second, your current directory is not in your $PATH. Therefore, you have to run the script with a path (relative is enough):
./script.sh

PS1='$PWD $ ' doesnt work from shell script

I am not a Solaris expert and I am trying to create a shell script that will change my prompt to PWD and the ksh to bash and I have this:
PS1='$PWD $ ' exec bash --noprofile --rcfile /dev/null
or
PS1='\w $' exec bash --noprofile --rcfile /dev/null
Both of them dont work from a sh. if i add them from the command line then the first time my bash appears on prompt and the second time the PS1='$PWD $' kicks in and my prompt changes.
Firstly, why is PS1='$PWD $' not working from shell script . and why do i have to run the command from command line twice to acheive my results.
Also, in my export/home/syed/ directory there are three files local.login, local.profile, and local.cshrc. is there any way i can use them that when ever i log in i dont need to run my shell script and upon login i get bash shell and my prompt as i want it
(am i asking too much, i dont like the ksh as it does not have any features like up arrow recall last commands and tab auto complete features)
thanks
Syed...
When you exec from within a script, the script is what is replaced, not the parent shell.
Try sourcing the script rather than running it.
Also, in Solaris, you can use passwd -e to change your login shell.
You may be able to symlink ~/.profile to your existing ~/local.profile (or similar). Note that .cshrc is for the C Shell and is not compatible with ksh or Bash.
If you want that your default shell will be bash, change it in /etc/passwd
When you exec bash it sets up its own environment from scratch. Pass it an --rcfile containing the settings you would like for it to inherit.

Writing a Bash script without the shebang line

I wrote a bash script under CentOS and it was executed well. On another computer it was wrong. I forgot the shebang at the beginning, but why was it good on my computer?
I assume it's a very beginner question, but I gave it a try. Thanks.
Updated:
Another question popped up. What's the difference between executing with ./filename.sh and sh filename.sh?
Not having a shebang in the beginning of your script will get it executed in whatever shell is currently running when the script was invoked. If you know for sure that the script will be launched from bash, and not from any other shell (ksh, csh, etc.), there is no need for a shebang, because the same interpreter will be launched.
If execve fails for your script, which it will, /bin/sh will be used. On one system /bin/sh may be a POSIX sh and on another it may be an alias for bash; your script probably relies on bash features.

How do I tell what type my shell is

How can I tell what type my shell is? ie, whether it's traditional sh, bash, ksh, csh, zsh etc.
Note that checking $SHELL or $0 won't work because $SHELL isn't set by all shells, so if you start in one shell and then start a different one you may still have the old $SHELL.
$0 only tells you where the shell binary is, but doesn't tell you whether /bin/sh is a real Bourne shell or bash.
I presume that the answer will be "try some features and see what breaks", so if anyone can point me at a script that does that, that'd be great.
This is what I use in my .profile:
# .profile is sourced at login by sh and ksh. The zsh sources .zshrc and
# bash sources .bashrc. To get the same behaviour from zsh and bash as well
# I suggest "cd; ln -s .profile .zshrc; ln -s .profile .bashrc".
# Determine what (Bourne compatible) shell we are running under. Put the result
# in $PROFILE_SHELL (not $SHELL) so further code can depend on the shell type.
if test -n "$ZSH_VERSION"; then
PROFILE_SHELL=zsh
elif test -n "$BASH_VERSION"; then
PROFILE_SHELL=bash
elif test -n "$KSH_VERSION"; then
PROFILE_SHELL=ksh
elif test -n "$FCEDIT"; then
PROFILE_SHELL=ksh
elif test -n "$PS3"; then
PROFILE_SHELL=unknown
else
PROFILE_SHELL=sh
fi
It does not make fine distinctions between ksh88, ksh95, pdksh or mksh etc., but in more than ten years it has proven to work for me as designed on all the systems I were at home on (BSD, SunOS, Solaris, Linux, Unicos, HP-UX, AIX, IRIX, MicroStation, Cygwin.)
I don't see the need to check for csh in .profile, as csh sources other files at startup.
Any script you write does not need to check for csh vs Bourne-heritage because you explicitly name the interpreter in the shebang line.
Try to locate the shell path using the current shell PID:
ps -p $$
It should work at least with sh, bash and ksh.
If the reason you're asking is to try to write portable shell code, then spotting the shell type, and switching based on it, is an unreliable strategy. There's just too much variation possible.
Depending on what you're doing here, you might want to look at the relevant part of the autoconf documentation. That includes an interesting (and in some respects quite dismal) zoology of different shell aberrations.
For the goal of portable code, this section should be very helpful. If you do need to spot shell variants, then there might be some code buried in autoconf (or at least in one of the ./configure scripts it generates) which will help with the sniffing.
You can use something like this:
shell=`cat /proc/$$/cmdline`
Oh, I had this problem. :D
There is a quick hack, use ps -p $$ command to list the process with PID of the current running process -- which is your SHELL. This returns a string table structure, if you want, you can AWK, or SED the shell out...
The system shell is the thing you see when you open up a fresh terminal window which is not set to something other than bash (assuming this is your default SHELL).
echo $SHELL
Generally, you can find out all the constants defined by running
set
If the output is a lot of stuff then run
set | less
so you can scroll it from the top of the command line or
set > set.txt
To save the output to a file.
Invoking a different interactive shell to bash in your terminal does not mean that your system shell gets changed to something else i.e. your system shell is set to bash although you invoke a csh shell from a bash shell just that one session.
The above means that typing /bin/csh or /bin/python in bash or whatever does not set the system shell to the shell you invoked, at all.
If you really want to see the SHELL constant change then you need to set it to something else. If successful you should see the new shell whenever you open a fresh terminal...
It's old thread but...
In GNU environment You can sh --help and get something like
BusyBox v1.23.2 (2015-04-24 15:46:01 GMT) multi-call binary.
Usage: sh [-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]
Unix shell interpreter
So, the first line is shell type =)

Resources