Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I have a script that is getting run by a third party environment which is running the script with "/bin/sh".

Is there a way from within the script that I can force bash to be used instead, for example by wrapping the commands in bash <<EOF ... EOF, like this?

#!/bin/bash

bash <<EOF
IMPORTS=$(find /home/snowch -type f -name .project)

for item in ${IMPORTS[*]};
do
   IMPORT="$(dirname $item)/"
   echo $IMPORT
done
EOF
share|improve this question
2  
make sure you quote the terminator: bash <<'EOF' –  glenn jackman Feb 11 at 20:54
1  
A bash script is not necessarily a valid POSIX shell script. Either convert your script to be POSIX shell compatible (which would be the best way IMO) or invoke it with the bash interpreter. The shebang line should do its job, that's what it's for. Run the script, don't invoke it with a wrong interpreter. –  Marco Feb 11 at 20:58
    
@Marco a user or an application might ignore the shebang by explicitly stating the shell to use. /bin/sh is not guaranteed to be the POSIX shell on every POSIX compliant platform. –  jlliagre Feb 11 at 21:15
    
@jlliagre That's why I suggested to run the script (in that case the interpreter might be unknown) instead of using /bin/sh as interpreter (which only works if the script language is bourne shell compatible). –  Marco Feb 11 at 21:21
1  
@marco My understanding is the script is run by a third party tool the OP cannot change/adapt. –  jlliagre Feb 11 at 21:48

2 Answers 2

up vote 3 down vote accepted

You might use this syntax which doesn't require the $ to be escaped unlike your here document attempt.

#!/bin/bash

bash -c '
IMPORTS=$(find /tmp/foo -type f -name .project)

for item in ${IMPORTS[*]};
do
   IMPORT="$(dirname $item)/"
   echo $IMPORT
done
'

Here is a more robust way (thanks to Gilles' comment suggesting it), that has the advantage to allow single quotes to be present in the embedded script:

#!/bin/bash

bash <<"%EOF%"
IMPORTS=$(find /tmp/foo -type f -name .project)

for item in ${IMPORTS[*]};
do
   IMPORT="$(dirname $item)/"
   echo $IMPORT
done
%EOF%

Note: there is no way to prevent someone to use a different shell than the one specified with the shebang. Writing a portable script (i.e. POSIX) script doesn't guarantee it will work with /bin/sh on every platform as the sandard doesn't mandate the POSIX shell to use this path.

share|improve this answer
1  
But then you can't comfortably use ' inside the bash snippet. A quoted here-document works better. –  Gilles Feb 11 at 21:23
    
@Gilles Thanks for your better approach, answer updated. –  jlliagre Feb 11 at 21:54

You could check from within the script if bash is being used. If not, replace the current shell with bash. If that fails, abort the script.

[ -z $BASH ] && { exec bash "$0" "$@" || exit; }

This would ensure that the script can only be executed using bash. (You might want to replace the complete path to bash in the command above.)

Note that as pointed by @Gilles and as noted in the following comment, this should be the first line in the script.

share|improve this answer
    
Yes, but if there were any definitions of shell variables above that point, they will not be available after the exec. For a self-contained script, you'd just start with #!/bin/bash or #!/usr/bin/env bash. –  Gilles Feb 11 at 21:22
    
Yes, I should have added that this ought to be the first line in the script. –  devnull Feb 11 at 21:26
    
If /bin/sh is actually bash then $BASH will have a value. So using -z isn't sufficient. –  bahamat Feb 11 at 22:32
    
@bahamat Unless I'm missing something, if /bin/sh is actually bash chances are that there won't be any issue in using bash specific constructs. –  devnull Feb 11 at 23:10
    
@devnull: bash has some behavioral differences when invoked as sh. I guess it really depends on whether or not that makes a difference. –  bahamat Feb 12 at 2:00

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.