When reading over Google's shell style guide, I found the following line that confused me a little: "Executables should have no extension (strongly preferred) or a .sh extension. Libraries must have a .sh extension and should not be executable."link At least when it comes to bash scripts, what exactly is the difference between an executable and a library of bash scripts? Are the scripts in the library not also executables?
4 Answers
At least when it comes to bash scripts, what exactly is the difference between an executable and a library of bash scripts?
I haven't heard the phrase "library" used much for shell scripts, and if I would, I'd suggest that the fact that the program needs to be split into libraries implies that it'd be better off implemented in some better programming language.
That said, I'd expect a library in shell programming would be similar to a library in other programming languages: something that provides functions and subroutines for other programs to use, but doesn't in itself do anything in particular with those tools. E.g. a library might provide the tools for compressing/uncompressing some data, but it would take a program using that library to implement a command line tool for compressing/uncompressing files named on the command line.
In practice, a program implemented in the shell would be just executed normally, like any program, while a shell library would only contain function definitions and would be sourced from another shell script, pulling those definitions in.
E.g. of the two files below, I might call main
a program, and functions.sh
a library. main
could made executable and executed as ./main
. (Or placed in $PATH
, but then functions.sh
also needs to be in $PATH
so that source
will find it.) Note that while you could run e.g. bash functions.sh
, it wouldn't do anything.
main
:
#!/bin/bash
source functions.sh
say hello world
functions.sh
:
say() {
printf "%s\n" "$*"
}
The point about executable programs not having an extension probably has to do with not exposing the implementation. The users of a program don't need to know how it's implemented, and in case a shell script is reimplemented in Perl, it's less confusing if it's not called foo.sh
, and less work if the name doesn't need to be changed (requiring modifications to all users of the program).
A library of shell functions can only be used from a shell script though, so exposing the implementation there does make sense.
-
If you are considering multiple front ends (CLI, yad, web of some sort), then it makes sense to have a clearly defined set of functions to perform the backend processing in a library. "some better programming language" may not be relevant if the purpose of the jacket is to invoke long running programs such as
dump
, it's just not worth the effort for a few uS saved in a couple of hours.– user516667Aug 5, 2022 at 22:06 -
@Martin, perhaps. But at least a web frontend probably isn't implemented as a shell script, so if the backend process is implemented as one, it'd have to be launched as as an independent executable. Executing that program would be the common interface for all the frontends. If that backend program is simple and again just runs some separate executable, it could well be a shell script. But if it's complex enough to need so many functions that it makes sense to put them in libraries, then yes, I'd suggest reconsidering if it should be a shell script or something else instead.– ilkkachuAug 5, 2022 at 22:28
-
Shell script libraries, like your example, can be very useful in the right place. In adapting a custom build system, written in shell scripts, to work with both iOS (hosted on Mac) and Android (hosted on Linux), I needed to write tools for collecting test data and pushing it onto devices. The pushing parts are quite different, but the collection part is almost identical, with the differences easily handled by a few tests. Implementing the collection system as a library of shell-script wrappers round
find
has worked very well. Aug 6, 2022 at 14:31
From bash's point of view there isn't a strict distinction between library and executables.
From the Google's style guide, the difference is explained in the section you described.
Libraries must have a .sh extension and should not be executable
Those files are usually a sequence of env variable and function definitions. Running them as an executable would do nothing. These files are only meant to be imported by other scripts.
The Google style guide encourages you to mark these with a '.sh' suffix to signal it to other programmers/maintainers.
The Google guidelines you reference are a little unclear, but they're talking about the file that contains the routines. They say a file that's written to contain a library of routines must not have any of the execute bits set, and it must have a filename ending in .sh
.
This kind of library file contains routines that will be invoked, but is not a script that performs a series of actions to accomplish specific work. So the code in the library file is executable, but the file itself is not "executable".
These are Google's guidelines for scripting. They describe a pattern of practices that will help people write pretty good shell scripts, but they aren't ironclad rules. IMO what they say about omitting execute permissions on library files is pretty good advice. What they say about the filenames doesn't matter so much (its not particularly good or bad advice).
I would suppose this refers to the filesystem attributes.
The binary and shellscript would have 'chmod +x' executable flags, the library script (so as not to be mistakenly called directly) non-executable.