path in shebang - bash

I have /bin/bash (3.2) and /usr/local/bin/bash (4.0) on my computer. In the $PATH environment variable, bash 4.0 is prior to bash 3.2.
in my bash script shebang, I don't like to explicitly use:
#!/usr/local/bin/bash
I'd like to find bash based on $PATH priority. How to do it? Thanks!

you can always try
#!/usr/bin/env bash

Related

$BASH_VERSION reports old version of bash on macOS, is this a problem that should be fixed?

I have homebrew's bash package installed. When I open a new shell:
bash --version gives GNU bash, version 5.0.7(1)-release (x86_64-apple-darwin18.5.0)
which bash gives /usr/local/bin/bash as expected.
But:
echo $BASH_VERSION yields 3.2.57(1)-release
I'm wondering if this is something I should address for scripts that might use this environment variable.
It means that the shell you're in is Bash 3.2, but bash points to Bash 5.0. Try bash and then, in the new shell, echo $BASH_VERSION – I guess it'll be 5.0. To change your login shell, add /usr/local/bin/bash to /etc/shells and change the default shell with
chsh -s /usr/local/bin/bash
sudo chsh -s /usr/local/bin/bash
After logging out and in again, $BASH_VERSION should be updated.
As for shebang lines, I recommend
#!/usr/bin/env bash
as it's portable and will use the first Bash in your $PATH.
The source of my problem was a terminal app preference setting. The "Command (complete path)" was set to /bin/bash. After setting it to "Default login shell", echo $BASH_VERSION reported the version I expected. The other problem is I stupidly ran the bash --version command in iTerm2, not terminal. So it gave a different response than what terminal would have.
Your login shell (see echo $SHELL) is probably /bin/bash and that is the one setting $BASH_VERSION. If you need to use a specific version in scripts, use the full path in the #! line.
Make sure to check that the terminal you are using is using the default login shell and not a custom one.

Refactoring bash command into tcsh command

I have problem with refactoring bash command into tcsh-friendly command. Don't know the tcsh syntax very well so the error im receiving doens't give me any clue.
The whole bash script was about adding modules on server
MODULEPATH=/app/modules/0/modulefiles:/env/common/modules
export MODULEPATH
module() { eval `/app/modules/0/bin/modulecmd sh "$#"` ;}
I changed first two commands to tcsh already
setenv MODULEPATH /app/modules/0/modulefiles:/env/common/modules
set MODULEPATH
But i dont know how to change the syntax of last command. Console is returning me error "Badly placed ()'s.".
Can I ask for little lesson what to change in this command to be tcsh-friendly?
chepner is right saying tcsh doesn't have functions at all and you'd have to write an alias instead. That's not much of an effort for your one-line function:
alias module 'eval `/app/modules/0/bin/modulecmd sh \!*`'
Basically, we prepend alias, remove () and {}, quote and replace "$#" with \!*.
The module command you want to port from bash to tcsh already comes with an initialization file to the tcsh shell. For all shells or scripting languages module is compatible with, there is an initialization file provided in the init directory of the software.
So from your example, Modules is installed in /app/modules/0, so you should have a /app/modules/0/init directory and a /app/modules/0/init/tcsh script to initialize the module command for tcsh. You just have to source it to initialize the module command:
source /app/modules/0/init/tcsh
As Armali says, the module command on tcsh is defined with the alias shell command.
With recent version of Modules (version 4+), you also have the possibility to define the module command in your current shell session with the autoinit subcommand of the modulecmd script:
eval `/app/modules/0/bin/modulecmd tcsh autoinit`

Parameter substitution bad substitution error on macOS High Sierra

The ${parameter[^|^^|,|,,][pattern]} parameter substitution is giving me a bad substitution error.
$ echo $greeting
hello world
$ echo "${greeting^}."
-bash: ${greeting^}.: bad substitution
I updated to the latest bash version and keep getting the error.
GNU bash, version 4.4.19(1)-release (x86_64-apple-darwin17.3.0)
I've looked everywhere and the only suggestion I've found is making sure it's running bash 4.
$ echo $SHELL
/bin/bash
I'm running macOS High Sierra.
Your default shell is not the bash shell (downloaded from brew install bash) that contains the v4 which supports the parameter expansion syntax you are referring to.
On macOS echo $BASH_VERSION will tell you the version of the current shell. bash --version tells you the version of the first bash in your $PATH. So the way you were looking at the version was not telling you the version that you were running.
You need to add the recent version of bash to the file /etc/shells as the last line and use the command to set the shell as the default on Terminal
chsh -s /usr/local/bin/bash "$USER"
After this close and re-open the Terminal to make it effect. Without adding this default option in your Terminal, you could only use the recent bash only on scripts with interpreter she-bang set to #!/usr/local/bin/bash
See also this Ask Different answer to - Update bash to version 4.0 on OSX

Change bash without making it default shell Mac

When running bash scripts inside zsh-Terminal I want it to use the homebrew bash version 4 instead of the default 3 of OS X.
How can I do that?
I installed bash 4 on my MacBook.
brew install bash
Instead of using it as the default shell using the following command, I want to keep my zsh.
chsh -s $(brew --prefix)/bin/bash # BAD! as I lose zsh
Still I want to run:
./my-cool-bash.sh
Use the following shebang in your scripts:
#!/bin/env bash
This makes them use the first bash in the PATH; which is the one you want.
This solution works with any Bash on any UNIX-like system.
use your new bash path:
ex, if new bash is in /usr/local/bin/
/usr/local/bin/bash my-cool-bash.sh
or write first line of script:
#!/usr/local/bin/bash
you could put an alias in your .zshrc file, something to the effect of
alias mcb='./usr/local/bin/bash/my-cool-bash.sh so that you can call it from your normal zsh whenever you want.

Shebang's relation to current 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.

Resources