Bash – Proper way to distribute shell scripts

bashshellshell-script

What is the most proper way to distribute shell scripts, if behaviours of shells can be modified by set and thus are unpredictable?

For example, rm *.txt wouldn't be executed as expected on the environments in which set -f has been run. How should I make sure that rm *.txt removes all text files in a current directory in any environments?

How should I make that sure that shell scripts will run as expected before distributing them in general?

Best Answer

Shell scripts are normally treated as if they were the same as any other kind of executable file, such as binaries, Python scripts, Perl scripts, or any other kind of script. They have a shebang at the top that directs the kernel to execute them through the shell. They are expected to be invoked the same way as any other command.

As such, a new shell is started every time the script is invoked, and any settings such as set -f present in the invoking shell or in any other shell instance in the system are irrelevant.

Of course it's possible for users to source your script instead of running it, for instance like this:

. /path/to/your/script

or to execute it in a shell that has non-default settings like this:

sh -f /path/to/your/script

but those are not considered normal ways or invoking your script, and users who do that should expect whatever they get as a result.

Note that there are some scripts that are intended to be sourced, not executed, because their purpose is to to things such as changing the cwd or setting environment variables that must be reflected in the environment of the sourcing shell, but these are in the minority and it's usually done as part of an agreed protocol. These files can be considered more like "plugins" to whatever system they expect to be sourced by, not so much as independent scripts. For example, files in /etc/rc*.d with names that end in .sh are sourced by the startup script subsystem, not executed, and it is documented that this is what will happen if you place a file with such a name in /etc/rc*.d and when it's done it's done on purpose. The convention of naming files intended to be sourced instead of executed in this way is followed elsewhere too, but not universally.

It's true that files intended to be sourced in this way have to take care of what settings might be present in their caller's environment that might affect the behaviour of the shell, but then the agreed protocol should ideally promise a predictable execution environment.

Related Question