Difference Between "#!/Usr/Bin/Env Bash" and "#!/Usr/Bin/Bash"

What is the difference between #!/usr/bin/env bash and #!/usr/bin/bash?

Running a command through /usr/bin/env has the benefit of looking for whatever the default version of the program is in your current environment.

This way, you don't have to look for it in a specific place on the system, as those paths may be in different locations on different systems. As long as it's in your path, it will find it.

One downside is that you will be unable to pass more than one argument (e.g. you will be unable to write /usr/bin/env awk -f) if you wish to support Linux, as POSIX is vague on how the line is to be interpreted, and Linux interprets everything after the first space to denote a single argument. You can use /usr/bin/env -S on some versions of env to get around this, but then the script will become even less portable and break on fairly recent systems (e.g. even Ubuntu 16.04 if not later).

Another downside is that since you aren't calling an explicit executable, it's got the potential for mistakes, and on multiuser systems security problems (if someone managed to get their executable called bash in your path, for example).

#!/usr/bin/env bash #lends you some flexibility on different systems
#!/usr/bin/bash #gives you explicit control on a given system of what executable is called

In some situations, the first may be preferred (like running python scripts with multiple versions of python, without having to rework the executable line). But in situations where security is the focus, the latter would be preferred, as it limits code injection possibilities.

Why is #!/usr/bin/env bash superior to #!/bin/bash?

#!/usr/bin/env searches PATH for bash, and bash is not always in /bin, particularly on non-Linux systems. For example, on my OpenBSD system, it's in /usr/local/bin, since it was installed as an optional package.

If you are absolutely sure bash is in /bin and will always be, there's no harm in putting it directly in your shebang—but I'd recommend against it because scripts and programs all have lives beyond what we initially believe they will have.

What's the difference of using #!/usr/bin/env or #!/bin/env in shebang?

#!<interpreter> <arguments> tries to run <interpreter> <arguments> to read and run the rest of the file.

So #!/usr/bin/env means that there must be a program called /usr/bin/env;

#!/bin/env means that there must be a program called /bin/env.

Some systems have one and not the other.

In my experience, most have /usr/bin/env, so #!/usr/bin/env is more common.

Unix systems will try to run <interpreter> using execve, which is why it must be a full path, and #!env without a path will not work.

Bash Script : what does #!/bin/bash mean?

That is called a shebang, it tells the shell what program to interpret the script with, when executed.

In your example, the script is to be interpreted and run by the bash shell.

Some other example shebangs are:

(From Wikipedia)

#!/bin/sh — Execute the file using sh, the Bourne shell, or a compatible shell
#!/bin/csh — Execute the file using csh, the C shell, or a compatible shell
#!/usr/bin/perl -T — Execute using Perl with the option for taint checks
#!/usr/bin/php — Execute the file using the PHP command line interpreter
#!/usr/bin/python -O — Execute using Python with optimizations to code
#!/usr/bin/ruby — Execute using Ruby

and a few additional ones I can think off the top of my head, such as:

#!/bin/ksh
#!/bin/awk
#!/bin/expect

In a script with the bash shebang, for example, you would write your code with bash syntax; whereas in a script with expect shebang, you would code it in expect syntax, and so on.

Response to updated portion:

It depends on what /bin/sh actually points to on your system. Often it is just a symlink to /bin/bash. Sometimes portable scripts are written with #!/bin/sh just to signify that it's a shell script, but it uses whichever shell is referred to by /bin/sh on that particular system (maybe it points to /bin/bash, /bin/ksh or /bin/zsh)

Why does /usr/bin/env bash -x only work in command line?

The short answer is that you only get one parameter to the interpreter which is specified via the "#!" mechanism. That became "bash -x".

Usually the limitation is more apparent, e.g., using

#!/bin/bash -x -i

would pass "-x -i" as the parameter, and get unexpected results.

Sven Mascheck comments on this in his page on the topic:

most systems deliver all arguments as a single string

Can't define variables when calling /usr/bin/env bash with execve()

Not sure where are you expecting the variables to be printed, but you need something like this

name[0]="/usr/bin/env";
name[1]="a=11";
name[2]="b=22";
name[3]="bash";
name[4]="-c";
name[5]="printf \"%d %d\\n\" $a $b";
name[6]=NULL;

What does the line #!/bin/sh mean in a UNIX shell script?

It's called a shebang, and tells the parent shell which interpreter should be used to execute the script.

#!/bin/sh <--------- bourne shell compatible script
#!/usr/bin/perl <-- perl script
#!/usr/bin/php <--- php script
#!/bin/false <------ do-nothing script, because false returns immediately anyways.

Most scripting languages tend to interpret a line starting with # as comment and will ignore the following !/usr/bin/whatever portion, which might otherwise cause a syntax error in the interpreted language.

When I type Anything in Ubuntu it returns /usr/bin/env: ‘bash\r’: No such file or directory

You have created an executable shell script with a shebang line #!/usr/bin/env bash. But you have likely created it on Microsoft Windows, and the line endings are \r\n (i.e. CRLF), instead of \n (LF) on Linux.

This does not work with shell scripts: you have to change the line endings to \n (Notepad++ can do that, for instance). What happens is, Linux reads lines separated by \n, so the first line ends with bash\r, and this is not the name of a known executable.

Note: this will fail not only with bash, but any script using a shebang: that can be Perl, Python, R, etc. That's because whatever the programming language, the executable is not called, because it's not found.

Note also that those programming languages usually read happily files with \r\n line endings. It's really the shebang line (i.e. executable scripts) that causes this problem.



Related Topics



Leave a reply



Submit