Common shell script mistakes (2008)
pixelbeat.org
pixelbeat.org
Emacs - https://github.com/koalaman/shellcheck
Vim - part of syntactic - https://github.com/scrooloose/syntastic/blob/master/syntax_c...
If you use OpenBSD and hate ports, then maybe ignore all the good things bash brings and write everything in Bourne shell. If not, then write bash. Just fire it up with '/usr/bin/env bash' to label it correctly.
Apple ships the last version that had a GPL2 license. That version gets older by a day every day.
On OS X 10.11.2, it seems to be bash 3.2 (http://opensource.apple.com/source/bash/bash-99/, via http://opensource.apple.com/release/os-x-10112/), which is from October 12, 2006 (https://lists.gnu.org/archive/html/info-gnu/2006-10/msg00006...)
I wouldn't call that slightly old.
Not for nigh on a decade, now.
* https://wiki.ubuntu.com/DashAsBinSh
* https://wiki.ubuntu.com/DashAsBinSh/Spec
* https://lists.debian.org/debian-release/2007/07/msg00027.htm...
You didn't even read the first sentence of the first hyperlinked page.
Even if bin sh links to bash, bash will still run a bin sh script in Bourne shell mode, stripping newer features, in some cases. Hence why proper scripts alway specify bash explicitly.
However I meant Bourne shell when I wrote 'ignore all the good things bash brings and write everything in Bourne shell.' Bourne shell being the original /bin/sh (though it's murky).
Do, again: whether bin sh is Bourne or Dash doesn't change anything, because a properly written script will specify its interpreter.
If Bourne is not comfortable or powerful enough for the task you're trying to do, you're using the wrong tool and Python is probably what you should be using.
I guess you think Bourne shell -> Python depending on complexity. I think bash -> Python depending on complexity.
As long as it's for your own system administration, sure. The moment it's being used for software intended to be used by third parties, no, the niceties of bash over bsh are not worth it.
Worth what? What do you lose?
Python is a good alternative as well.
For instance, for the first time in 15+ years, I recently had a reason to use Perl's half-deprecated, off-handedly-included form printing support, and, you know what? It's really nice if that's what you want. Many dozens of lines of code replaced by what is basically a picture of what I want.
Python is a great language, but every once in a while "explicit is better than implicit", which is generally a philosophy I agree with wholeheartedly, results in a lot more "explicit", in the form of "code I had to write", than you might be looking for. (Or, alternatively, you start writing Python that is a lot more implicit, which isn't exactly a huge victory for Python here.)
Nowadays I'd also suggest that if you find yourself having a lot of those tasks, you need to ask some questions about how you're storing your data. But pretty much everybody ends up with some of these somewhere; it's hard to eliminate them, and not really worth it (due to diminishing returns).
so I just installed perl 5 and did it my usual way. But if I didn't know Perl already it would be a non-option. it's just not a language anymore, it's a legacy thing that if you already learned you can sometimes still use.
An younger developer may think differently, but I do think the 'Perl' brand is already too damaged for surviving the transition, even if Perl6 is better than modern languages (what I didn't see anybody claiming yet).
instead use something with a cross-platform interface (Python, Chrome or Lua, whatever), compile your own executable or use a compiler that targets bash.
besides, it is only a matter of time before the systemd trojan invades this area, and your newly acquired skills will be obsolete </sarcasm>.
if [ "$var" = "find" ]; then
echo "found"
fi
Is far more readable than its equivalent [ "$var" = "find" ] && echo "found"
I understand the upside of readability. What does concision get me?most programmers seems to prefer verbosity.
however in my case verbosity slows me down.
If that's the only criterion, then the parent just followed the logic. Or let's put it another way, if the definition of readability can't survive taking it to the extreme, it is flawed.
wodenokoto offered up some reductio ad absurdum and you are calling it logic.
It was not the only criterion. It was the only criterion that was explicit. There are implied criterion and most of us understand what pwd_mkdb means even if we don't necessarily agree with him.
Well, even in itself, it is wrong.
It's not just that other criteria apply too -- it's that it alone needs several caveats, as succinctness is quite orthogonal to readability (e.g. sometimes even needless boilerplate syntax that the compiler could infer by itself, make for better readability when present).
I am not in disagreement with you about whether it is wrong, I am in disagreement with you about why it is wrong.
The counter argument was that Y is wrong and X is Y, therefore X is wrong. While this is a valid argument, it is not sound, because X is not Y.
> ... succinctness is quite orthogonal to readability ...
There is a relationship between succinctness and readability. The relationship is definitely not directly proportional as the pwd_mkdb's post could be read to imply, but to say there is no relationship between the two is flatly absurd.
That's a bad definition. Readability should be: "code easier to read", not just "less code to read" -- since less is not always easier and can even be much harder.
Case in point: the J language.
Or "magic" constructs that do too much under the scenes and don't let you immediately understand what a part of code is doing.
Concision gets you fewer places to possibly have a bug, and fewer things to possibly miss/misunderstand.
"Inappropriate use
shell is the main domain specific language designed to manipulate the UNIX abstractions for data and logic, i.e. files and processes. ... Correspondingly, please be wary of writing scripts that deviate from these abstractions, and have significant data manipulation in the shell process itself. While flexible, shell is not designed as a general purpose language and becomes unwieldly when ... "
Another person has actually solved the most important show stopper already: http://ctypes.sh.
What now remains to be solved, are a few minor, additional details, and then simply writing a good manual of how to very successfully use bash as a general-purpose language.
My personal belief is that everything that you can do in other scripting languages, you can also do in Bash, only better.
Matrix multiplication?
For another example, jq and jshon are excellent tools for querying, transforming, or creating JSON values.
My experience is that programming by composing Unix programs that communicate via pipes and files can be very pleasant and productive.
Sometimes I lament aspects of bash syntax and semantics, but it's also much more convenient than other scripting languages for tasks related to spawning programs and pipelines and working with files.
One of my recent projects that I've been having a lot of fun with is a kind of continuous integration system built mostly with bash scripts. It involves a lot of calls to git and Docker, process manipulation, file descriptor redirection, and file system manipulation—and bash makes all this pretty easy and concise.
>> My personal belief is that everything that you can do in other scripting languages, you can also do in Bash, only better.
1) Native JSON, XML
2) Classes, namespacing, objects
3) Multiprocessing, multithreading
4) Performance
5) Package management
6) Portability
7) Documentation
8) Runtime debugging (!set -x)
I'm too tired to continue.
In case you're not, here are some "Bashisms" that really suck to be without:
* built-in regex support (e.g. `[[ $var =~ ^1\.2\.[34]$ ]]`)
* process substitution (e.g. `diff <(before_command) <(after_command)`) and all sorts of other redirection tricks
* indexed and associative arrays
Some of this can be worked around by shelling off to grep for regular expression matching or awk for arrays, but Bash makes things so much cleaner and maintainable.
And even if you do install it, it still won't work with scripts that specify /bin/bash (which is a lot of them, thanks to sloppy tutorials), since it will be in /usr/local/bin and not /bin.
* http://unix.stackexchange.com/a/250965/5132
* https://debian.org/doc/debian-policy/ch-files.html#s-scripts
* http://manpages.ubuntu.com/manpages/xenial/en/man1/checkbash...
* http://manpages.ubuntu.com/manpages/xenial/en/man1/posh.1.ht...
The answer is, of course, lots of them; as there was a massive project to do exactly this in Debian and Ubuntu some years ago.
When I mentioned embedded systems I primarily thought of Linux/Busybox-based devices, like OpenWRT. While one surely can have bash there, usually base image doesn't contain it.
Same story about the most common Linux-based OS out there: Android. And, while it's no one manually runs shell scripts there, apps quite frequently exec() things, so shell scripting still matters there - a tiny bit. Also, shell scripting is heavily used in firmware upgrades/patches, as well as a glue for the root/unlocking hacks.
If you plan to write a redistributable component or an useful hack for such platforms, you'd best stick with a very limited subset of POSIX.
this should not be construed as an argument in support of /bin/sh.
A few hours ago; and before that, last Wednesday. The latter says:
JdeBP % /bin/bash
zsh: no such file or directory: /bin/bash
JdeBP %
The Z Shell is an add-on here, too. /bin/sh is the Korn shell. No, it's not OpenBSD.AFAIK in POSIX /bin/sh it's not possible to detect if a process that writes into a pipe exits with an error status.
bash has "set -o pipefail" and "$PIPESTATUS" for that.
IMO shell makes it very easy to work with multiple process (&). It's built in and natural.
>4) Performance
If you are carefull and know what you're doing, you can achive very good performance with the shell. Usually, better performance is achived processing less data, ie being inteligent. Rarely depends on the language (unless you care about cycle level performance, then yes :).
>6) Portability
I claim that it's way easier to depend on sh being on a (UNIX) system than $SCRIPTING_LANG.
>7) Documentation
?? You can mess up documentation in any language.
What I would like in bash is some easy way to limit the number of background processes I can spawn, and to just wait when I try to start another one until an existing one is finished.
Some simple jobs can be converted to use xargs -P, but for more complex things I end up having to do them without parallelisation, so I don't end up spawning 100s of background processes and bring my computer to it's knees.
But limiting the # of spawned children is possible using not so complicated ad-hoc solutions, but I guess it depends on the specific problem.
It pretty much doesn't do anything else that you might want to do with multiple processes, though, and it tends to encourage multiple processes to communicate via text which is a problematic limitation that one often finds oneself "working around".
Shell is really powerful, but it hits a certain limit of what kind of tasks it can do and it hits that limit hard, and that's why when one imagines orchestrating many processes on a machine to do some task, to say nothing of orchestrating many processes on many machines, you don't see solutions based on shell, and indeed the very idea is laughable. Shell is best used by making sure it stays firmly restricted to the domain it shines in and not so much as trying to dip a toe into the spaces where it is not.
[1]: Note "not much fun" != "can't". Shell is fundamentally written around the idea that a process has one stream STDOUT that may go to other processes, and one stream STDERR which is generally intended to go to the console (or other user output like a log) no matter how complicated the pipeline. While you can get both streams and do things to them, you're starting to fight shell, which really wants to create pipelines with one "through" path with no branches out.
In a POSIX conforming shell,
&> word
is the same as & > word
since '&>' is not a distinct token; it puts the command in the background and redirects standard output.The more commonly seen >& will bite you even in bash. What does this do?
>& $FILENAME
Answer: in bash, it depends on the spelling of the file name.Note that bash accepts both even in its so-called ‘POSIX compatible’ mode.
I appreciate he mentions this first. Shell scripting is excellent in its domain, just as SQL is great in its.
You would write an application in SQL and you shouldn't write one in shell.
Will this work if you've activated set -u, fail on unset variables? Will the !-z variant do?
Don't" [0]
[0] MIT, writing safe shellscripts ~ https://sipb.mit.edu/doc/safe-shell/
https://github.com/Gabriel439/Haskell-Turtle-Library
Related: http://www.haskellforall.com/2015/01/use-haskell-for-shell-s...