Also, JavaScript really is not a very good programming language. We are just stuck with it because it's the only language the browser understands. (Well, until recently: things are going to change with the introduction of wasm).
But for the shell, we're not stuck with any one language. Whatever you want to do can be programmed in your favorite language. You can easily write a python script instead of a bash function.
people have been saying this for years already and nothing seems to have come of it :(
There aren't many languages that are practical for WASM output. Scripting and managed languages need to ship their interpreters and runtimes with their WASM blobs, and can end up relatively large. JavaScript's interpreter and runtime are baked into every browser already.
That leaves only compiled and unmanaged languages for potentially good WASM targets. As mentioned before, Rust is seeing a lot development in that space. If LLVM can compile it, then Emscripten can output it to WASM.
Figma for example seems to be largely powered by WASM and the core of the product seems to be written in C++
https://www.figma.com/blog/webassembly-cut-figmas-load-time-...
https://www.figma.com/blog/building-a-professional-design-to...
I think the majority of web developers are just slow at catching up with this new things.
I thought that was the case but I can’t recall where I read it. If that’s not true then I should probably reconsider my thinking about wasm
We've been forgetting and relearning that for the past two decades.
Actually it turns out that having an interpreted runtime causes a stream of endless problem. We keep try to patch them over but new problems keep coming up.
It turns out that a standarized low level byte code is the right way to ship cross platform applications. We already knew that. It just took a long time to go through the standarization process and be implemented by browsers.
If it seems like it's not in use today, it's largely because JavaScript has momentum and the majority of web programmers don't yet know how to take advantage of wasm (or maybe don't think they need it).
So why hasn’t it taken over the world with Java and now with wasm?
> If it seems like it's not in use today, it's largely because JavaScript has momentum and the majority of web programmers don't yet know how to take advantage of wasm (or maybe don't think they need it).
There’s another possible reason. I’m sure you can come up with the answer yourself.
Java applets really sucked. They took a long time to load and initialize. They all looked ugly (probably because of the default libraries?).
Also Java itself as a language was really bad and the development experience was awful. I want to say that no one wants to program in Java but in reality many people do (I don't understand those people).
The important lesson here is the implementation is more important than the idea.
Good idea with bad implementation -> goes no where.
wasm is not java.
The important quality about wasm is that it's not garbage collected. It's pretty close to just good old assembly.
Chrome was released at the end of 2008, JavaScript was thriving way before that. We had Gmail since 2004, jQuery since 2006. WebApps were the “sweet solution” considered for iPhone apps at first in 2007. Chrome exists because of the healthy ecosystem that Firefox and Safari provided, not the other way around.
>It's pretty close to just good old assembly.
Precisely, and it's yet to be proven that's the best solution for the Web. I love it from the computer science perpective, but historically that idea hasn't struck a chord.
> JavaScript really is not a very good programming language.
Since 2015, JavaScript really is a nice language. I never thought that I'd say that.Go look at ES6 (the javascript version that came out in 2015) and even TypeScript. You'll be pleasantly surprised, no matter if you're coming from C++, Java, C# or even other "scripting" languages such as PHP and Python.
Ultimately I want a langauge with value types like structs and arrays that you can use to do computations without allocating things on the heap.
In Go I can write a function that returns two numbers.
In Javascript I can only return two numbers by allocating an array on the heap with two items. These two items themselves are probably pointers to two number objects allocated separately. So that's 5 allocations to return two numbers. It's insane.
This means fundamentally it's impossible to create applications in javascript that are both sophisticated and high performance.
A great example to illustrate this is the tooling around Javascript itself.
There were all kinds of bundlers: webpack, rollup, parcel, etc. Rollup was considered the fastest and lightest. They were all programmed in Javascript itself. They were all slow. But no one really knew how bad it was because there was nothing really better.
Then esbuild comes along, and blows all of them completely out of the water, out performing them by 100 times. And it's written in Go. A language that supports structs and arrays as value types.
For example, you are worried about value types but under the hood the JIT compiler will actually generate efficient representations that are passed by value if you do not mess things up for it. Modern JS compilers are extremely sophisticated.
For returning values without an allocation, you’d create such a “struct” and then use a memory pool. It would still be heap allocated I believe but not totally sure. People who know more than I do could probably tell you a better method to return multiple values from a function efficiently.
Yes, and in my experience this kind of applications (and the browser in general) are one of the only things these days that still push me to upgrade my hardware to have better CPUs and more RAM, as it's perfectly sufficient as is for pretty much everything else I do.
Its tooling got significantly better in the last decade or so, but you still need to intentionally rely on it in order to work with the language in any sensible way. You can't really hope for any other outcome when maintaining backwards compatibility.
Everything else is either unmanageably complicated (webpack) or slow (rollup, parcel, babel).
React mainstreamed the idea of using a virtualdom to accelerate UI building (accelerate in the computational sense: by not dealing directly with the slow DOM).
A couple of years ago, I challenged myself to write some complex scripts and apps using only Bash, and came to this conclusion myself.
You can get pretty far with just Bash alone, especially if you strive to write readable and maintainable code, and not just one off scripts. If you need access to data structures, especially nested ones, you can shell out to another language and then print the results back to stdout so Bash can use them:
$ get_data | transform_data | python3 ./complex_script.py | consume_resultsI just hate doing things with files in the shell, all those stupid escaping rules, and god forbid you have files with spaces or quotes in the names, or leading or trailing spaces.
It's just spending time learning hacks to get around shell limitations instead of actually getting things done, and at the end it's an ugly mess.
Or maybe I'm just bad at it, but I don't think it's only that.
Packaging in Python is a bit more of a pain.
> Windows doesn't have bash preinstalled
I meant Python preinstalled. > On all OSes I've used in the past 3-4 years all of them have been Python3 by default.
Windows comes with Python preinstalled now?should read
"no reason to think ... couldn't"
You can use I/O redirection with arbitrary file descriptor numbers, and you can let the shell pick them. So you can `mknod` a pipe, `exec {pipefd_rw}<>"$pipe_name" {pipefd_ro}<"$pipe_name" {pipefd_rw}>"$pipe_name";` and now you have three open file descriptors that you can let the sub-shell use to communicate with the parent. And so you're not limited to stdin/stdout. I do wish there was a built-in for making an anonymous pipe instead of having to make one on filesystem.
(You have to open the named pipe for read-write first because otherwise you'll block, but if you don't want a read-write FD for it you can close it after opening the read and write FDs.)
I'll count myself among nobodies, I guess. I use them a fair bit when part of said subshell cd's somewhere, and I don't feel like using pushd/popd, either of which might fail to operate based on my mistakes, but subshells seem to never fail to exit, eventually.
On the other hand, I wonder if the web page keeps track and could offer "best of bash mistakes".
"ShellCheck is...
* GPLv3: free as in freedom
* available on GitHub (as is this website)
* already packaged for your distro or package manager
* supported as an integrated linter in major editors
* available in CodeClimate, Codacy and CodeFactor to auto-check your GitHub repo
* written in Haskell, if you're into that sort of thing. "
Sometimes you are not in your computer, the script does not have private information (i.e. open source or something you don't care to be public). Sometimes the website is simply more convenient.
*edit: formatting
But if you're still using Windows, then yes, I agree.
The thing with bash is, it's great for tying things together and quick bits and pieces, but it's not set up for writing maintainable code. Arrays, functions, even if statements comparisons can all be done in bash (as first-class features), but are just... easier in other languages. And then think about the refactoring, linting, testing tools available in bash vs other languages. And then on top of that, there's the issue of handling non-zero return codes from programs you call; do you `set -e`, and exit on any non-zero return code even if you wanted to continue, or not `set -e`, ignoring any errors as your script just continues.
Personally, when I feel I want to use a function (or array, or other similar, non-trivial thing), in bash, it's time to reach for another language.
Having said that, there are some nice programs written in bash. https://www.passwordstore.org/ being one that comes to mind.
Python is strongly typed. Maybe you meant "statically"? (As opposed to dynamically.)
Then you must not be writing any bash at all. Functions are useful for almost anything beyond a one-liner script.
Typical functions used in innumerable non-trivial scripts:
* print_usage()
* die() (see: https://stackoverflow.com/q/7868818/1593077)
:-)
With regards to `print_usage()` and `die()`, yes, I would reach for Python 3 then. The `argparse` module and `throw` are first-class members of the stdlib/language and are better and more standard between programs than if I threw together these myself (and with `throw` you get a stack trace, which is nice).
https://github.com/GavinRay97/hasura-ci-cd-action/blob/a9731...
This is out of necessity. I'm not the sharpest tool in the shed, so I have to go out of my way to write things such that when I come back to them in months or years, I still understand what they do.
For this same reason, is also why I never use shorthand flags for scripts.
I have no clue what IE: "-s -y -o" might do (or even worse, "-syo", dear god my eyes! Also -- is that one special command, or a series of individual commands?!).
But "--silent --assume-yes --output-file" is pretty easy to grok immediately.
Oh man this is so ugly
Not something I would expect in an "elegant" script. Don't think that it is your fault, just it is very hard to write anything elegant in bash.
Hahaha -- fair point. Readable: maybe. Elegant? No. Bash is far from elegant =P
Sorry if I missed something in the logic, reading on my phone, but from the comment, this feels like something I do frequently...
https://ilya-sher.org/2021/03/19/running-elegant-bash-on-sim...
Parsing command-line arguments is easy, but parsing them correctly is ridiculously hard. `getopts` doesn't handle long flags, so it's out. `getopt` doesn't handle arguments with spaces in them, unless you have a version with non-standard extensions, so it's out. You're left with manual parsing, and it's a royal pain to make sure you handle every expected case (short/long flags, clusters of short flags, trailing arguments to be passed through to a subprocess, short/long options whose value is in the next argument, long options whose value is after an equals sign, and several others I'm probably forgetting about). And this is just to get the arguments into your script, before you actually do anything with it.
I agree that bash has effective idioms, and learning those idioms can make scripts easier to write. I strongly disagree that bash is "as maintainable as anything else", and scripts beyond a few hundred lines should be rewritten before they can continue growing.
while getopts :i:h-: option
do case $option in
# accept -i $input-file, -i$input-file
i ) input_file=$OPTARG;;
h ) print_help;;
- ) case $OPTARG in
help ) print_help;;
help=* ) echo "Option has unexpected argument: ${OPTARG%%=*}" >&2; exit 1;;
in=* ) input_file=${OPTARG##*=};;
in ) echo "Option missing argument: $OPTARG" >&2; exit 1;;
* ) echo "Bad option $OPTARG" >&2; exit 1;;
esac;;
'?' ) echo "Unknown option $OPTARG" >&2; exit 1;;
: ) echo "Option missing argument: $OPTARG" >&2; exit 1;;
* ) echo "Bad state in getopts" >&2; exit 1;;
esac
done
shift $((OPTIND-1))Is there a feature I'm not seeing that would generate an argument parser without external dependencies?
...
--foo)
FOO="${2:?ERROR: String value is required for \"-f|--foo\" option. See --help for details.}"
shift 2
;;
--foo=*)
FOO="${1#*=}"
shift 1
;;
...Is there a reason we aren’t using a shell with a proper programming language for scripting?
I can’t say I’m a fan of bashscript. I wonder why we are using this weird language.
After all, HTML got much better when WHATWG took W3C's toys away and actually started innovating HTML again. Maybe it's time to do something similar with Unix: I'm sick and tired of people telling everyone that we have to stay in some 1995 time capsule because we need to follow The Standard and if The Standard hasn't changed, too bad.
De-facto standardization has at least brought us free officially-supported options for running Bash or other *nix shells on both of those platforms(if terribly outdated on Mac).
Maybe it'll be like the C++ vs Rust situation?
$ cat "file.txt"
...and I don't even know what options would look like... maybe: $ ls "*.txt", ["l", "a"]
I dunno... this would mean we'd probably need parens now for precedent-type concerns: $ ls("*.txt", ["l", "a"]) > "file.txt"
Anyway, that is why I understood that it's this way. I can't point to a resource about it, though.Also powershell has no support for automatically handling external shell commands that error, you must manually check $LASTEXITCODE (easily done with a custom invoke api that you use for everything).
Also well, some of the escaping in strings is really odd...
With bash (and I suspect with every other popular shells out there), it actually means something different. In your second example, if you don't use quotes, the shell will do the extensions, but if you do, the process will have to do it (and in the case of ls, it cannot).
In some case it's good to have the shell taking care of it, but sometimes (eg, when using 'find') it's not.
I was trying to point out that quoting parameters or not could bring a different meaning for a shell (as one could see it with Bash), with the implied consequence that one would have to carry over that nuance somehow to a shell where all parameters would have to be quoted.
Here are the ways to run a program in ruby https://stackoverflow.com/questions/7212573/when-to-use-each...
https://research.swtch.com/shmacro
The Bourne shell thus adopted ALGOL syntax, distinct from anything else in UNIX.
David Korn brought a pile of C, and wedged it into a max 64k program space (for Xenix), and his upward-compatible Korn shell (ksh88) had many, many features.
Then there were the "UNIX Wars"...
https://en.wikipedia.org/wiki/Unix_wars
The fallout of this was the choice of a few Korn features, but not all (no arrays, coprocesses, [some] eval, regex, et al.)
The wars defined the POSIX shell. Yes, it can be infuriating.
There are two very distinct places where Bash is not, that I have found.
Bash is not in busybox. It pretends to be, but what is really there is the Almquist shell, with a bit of syntactic sugar to silence the common complaints.
Bash is also not in Debian's shell (/bin/sh). In that place, there is no tolerance of bashisms.
It is important to know the POSIX shell for these reasons.
The Android userland explicitly avoids any GPL software.
The Android system shell is the MirBSD Kornshell (mksh).
This is (obviously) a massive platform.
When writing a bash script, shouldn't you be setting the shebang to /bin/bash which is available on Debian?
It is otherwise advisable when speed or portability are required.
You have to step back and remember the point of all this. Why are you programming? To solve a problem, and make a human's life easier. What is the problem you are trying to solve? How can we make the human's life easier? In this case, it's "I want to combine bunch of programs together in a command-line interface, to make it easier to use these programs to get my work done on the command-line." So, what solution should we choose for this scenario?
Lots of different "scripting" languages exist (we used to call them "glue languages"). Today Python is the most popular, and before it was PHP and Perl. But who cares if they're popular? What are they good for? Why would you choose one over the other?
Python is a general purpose language which is easy to learn, easy to write, and easy to read. Well that sounds nice, but it's very "general" and not specific to our use case. PHP is a language designed for use in web development. Perl is a language designed for system administration-type tasks.
Bash scripting is designed for making it easy to combine already-existing programs in a command-line shell, with no modification or creation of programs required. The only "dependency" is the Bash interpreter (which happens to also be the command-line interface we started our problem with! how convenient!) and an existing collection of software tools that work with each other through a command-line interface. Every part of it is explicitly not designed to "make programming easier". Instead, it is designed to make "combining programs in the command-line" easier. The result is things like every single word you type is potentially just an outside program being executed, or arguments to that program. No other language has this quirky behavior, because they're not designed solely to make command-lines easier to use.
I know Perl well, and the language is fantastically useful as a system scripting language. It combines some of the best features of common shell scripting programs with more programming language-specific features. It is designed with shortcuts and "magic" to make quick work of command-line scripting tasks. But ultimately Perl was not built into the command-line, so its utility is always a bit stilted. Going between the shell and the Perl code and back to the shell isn't as flexible as if the Perl code was embedded in the command-line. Perl also doesn't have as simple a facility for pipes as a command-line shell does. Oh, and a Perl install is rather large, isn't available everywhere by default (anymore), and has all the usual dependency problems. So even though I know Perl very well, if I need to just combine existing programs in the command-line, I always use Shell scripting instead of Perl. (There are Perl shells which solve this problem, but then everyone needs to learn Perl, and Perl can be.... idiosyncratic)
You could also use Awk for a large number of general programming tasks, but again it's designed for a different specific problem: pattern-scanning and processing, not generally combining programs together.
So we use shell scripting to solve the problem because it was designed specifically for our problem, it's ubiquitous, and simple to use. You could use any other programming language, but it wouldn't fit our scenario as well. Once your use case changes, and you are no longer only trying to combine existing programs together, or the existing programs don't do what you want them to do, then you need to use a different language that better fits that new use case.
Mostly because the people who want to introduce a "programming language" into the shell don't prioritize being a shell.
Check out the "Oh" shell for contrast. This is what a programming language looks like when you force it to conform to being a shell first priority.
https://github.com/michaelmacinnis/oh
https://www.youtube.com/watch?v=v1m-WEZz46U
This is "Scheme-like" (actually the late John Shutt's Kernel-like) but has FEXPRs so things can be redefined and evaluation can be controlled.
However if I’m not careful they get painfully complex and I tend to regret not writing it in perk. As such I now switch to using Perl when I get to the function stage, or anything other than the most simple bash arithmetic.
I've still not found a suitable answer.
> Getting anything out of a subshell that isn't from STDOUT is impossible.
Yes that is a known limitation that has horrible, horrible workarounds. Don't use them.That said, for scripts whose main input _is_ from a file or STDIN, and also whose main output _is_ to a file or STDOUT, then bash is far more often the right tool for the job than it is given credit for. Of course, I'm talking about bash and a host of other utilities that are often packaged with it such as awk, grep, sed, cut, etc.
For processing text I find myself often choosing between bash and Python, and very often if I choose bash I'll feel that I've made the right choice.
djb has always used them, even in the shortest of scripts.
Otherwise I agree with everything in this comment.
There is a reasonable argument to avoid using bash for non-interactive scripts. The benefits of any additional bash features, so-called "bashisms", arguably do not outweigh the costs of making these scripts non-portable. One of the many advantages of shell scripts is that they are portable and have tremendous longevity; shell scripts can last a long, long time. There are no version changes and aggressive feature creep to worry about as is routinely the case with programming languages. The scripts just keep working, every day, and we can forget we are even using them, e.g., they are being used in the various ways by UNIX-like OS distributions.
One of the today's programmer memes was "Get Stuff Done". Maybe the shell was not meant for today's programmers. But for "sysadmins", or "DevOps", or whatever term anyone comes up with in the future, people who can "administer/operate" computers running a UNIX-like OS for themselves or for someone else like a client or an employer, the Bourne shell works for its intended purpose, better than anything anyone has come up with in the last 50+ years. There's a lot of stuff that "gets done" with the shell, whether it is on someone's own computer, their client's or their employer's.
Attempts at "shell replacements", cf. alternative shells, usually look like interpreters for programming languages, not shells. Perhaps this is not a coincidence.
Bourne shell is relatively small and fast. Computers with small form factors often use UNIX-like OS and when they do they usually include shells. Many programmers seem to dislike the notion that such a layer exists. They often try to blame the shell instead of their own lack of interest in learning to use it.
The shell is boring, and "boring" is sometimes the wisest choice. Most software has expanded to consume available resources (often the developer's choice not the user's). This makes computer performance gains difficult for the end user to discern, e.g., decade after decade, routine tasks seem to take the same amount of time. However the shell and many "standard" UNIX utilities have not changed as much in the same period. Subshells may have been "slow" many years ago. IMHO, they do not feel slow today. Routine tasks performed with the shell seem to run faster, as one would expect after hardware upgrade.
I posit: Life is too short to learn every programming language du jour but it is long enough to learn the Bourne shell, reasonably well.
If scripts written for a POSIX-like "lowest common denominator" shell were not portable, methinks projects written for such a shell, such as autoconf, would not work on so many diffferent systems. The amount of free software found in open source OS repositories that is built using "configure" shell scripts is not small.
Debian and other Linux distributions use a shell derived from NetBSD's Almquist shell. People who design and maintain these operating systems suggest that, for non-interactive use, this Bourne shell is faster than Bash.
They have to shell out to other commands in order to do something meaningful.
Depending on your OS, these commands may not exist, or have a different set of commandline flags.
Mind, if possible, it is even uglier than using stdout.
err_f="$(mktemp)"
third_f="$(mktemp)"
out="$(cmd 2>"$err_f" 3>"$third_f")"
err="$(cat "$err_f")"
third="$(cat "$third_f")"
Seems like that should work fine, and it's not even that odd looking or hard to understand. But I haven't tried, not sure if there's some surprise lurking in the depths of tempfiles or something.The fact that there isn't a good way to open an anonymous pipe and get its two file descriptors in bash is very annoying.
> avoid bashisms
What's holier-than-thou is insisting that people stick to a dialect of shell scripting that hasn't changed in decades because some people think that conforming to POSIX is its own reward even if it makes life harder and programs worse.
No, thanks. I'll stick to bashisms. Things like coprocesses and filemap make certain classes of program much easier to write. And yes, shell scripts are programs, and the quickest way to turn these programs into unmaintainable balls of mud is to follow your advice to avoid normal programming best practices simply because the program you're writing happens to be a shell script.
#!/usr/bin/env bash
process_line() {
if [[ $* == *foo* ]]; then
echo "found_foo=1" >>$IPC
fi
}
IPC=$(mktemp)
find . -maxdepth 1 -type f | while read line; do
# note: this is run a subprocess
process_line "$line"
done
source "$IPC"
echo "found_foo=$found_foo"Bash is definitely a different paradigm to your average imperative or functional language and thus requires a different approach but I wouldn’t go so far as to say it’s not “real”.
It certainly fits the criteria of a programming language even if it does have more warts than a pantomime witch.
Compared to other languages, Bash can be incredibly worse for some things, but much better for others.
People who don't realise that won't be able to get the best out of their toolset.
No. It’s still an interesting yard stick. It just doesn’t describe programming languages in full. For example, and someone counterintuitively, it is actually possible to design a programming language that isn’t Turing complete. Some esoteric functional languages do actually fall into that category. But generally programming languages would be a subset of Turing complete software.
> And on that same note, have you seen the stuff being done in Minecraft?
I have, hence why I cited it as an example.
> It is quite up for debate whether it is a programming language.
One could debate anything but it doesn’t mean the argument is made in good faith.
Minecraft is a game. I’m happy to even extend the definition and say it’s supports some visual programming mechanics. But that doesn’t mean it is a programming language.
Just because something has 4 legs and a tail, it doesn’t automatically mean it is a dog.
If anything you are saying it should be deprecated in place for a real language. If people want to do more advanced things why does the basic language of their shell not support it? Why should you not care about the correctness of your shell scripts which can run important things? Seems a perfect place for a functional language. It’s high level, you can just declare what you want. I imagine your interpreter can add in all sorts of checks to help make your scripting more correct.
And it’s a horrible shell experience.
It’s great for scripting (but not as good as other scripting languages) but it’s a terrible experience on a day to day basis, with the only salvation being the existence of 2-3 letter aliases which make things slightly more manageable.
Bash is a great shell language that whose scripts are useful because it allows you to trivially convert your manual shell actions into an executable script.
If you need to do anything complex (or rather, something you probably wouldn’t type into the shell manually if you had to do the thing on a one off basis), then you’re probably better off using a different scripting language.
But changing BASH with scripting as a priority would probably make it a worse shell language (which is not to say there are no improvements to be made…there are).
Huh. How does one return a value from a bash function? I've always only ever seen the "echo calling convention" used in scripts, or use of global variables.
Since all valid "sh" syntax is valid "bash", you've got to restrict yourself to only sh-valid code in the event the host doesn't have bash.
I have gotten used to doing this -- these scripts usually wind up being run in Docker containers that don't have "bash" installed for the sake of minimalism.
IE, you can't use [[ $predicate ]], but instead [ $predicate ], etc. Lot of subtle differences.
The supersets of POSIX are often even more effective.
Ugly as the tool may be, in the box it stays.
It’s generally considered best practice (in the functional programming community at least) to write “pure” functions (that is, functions without side effects) because it’s much easier to reason about what they are doing.
So good news, subshells can _only_ be pure (the only way to get anything back from them is if they write some string to stdout), but sometimes you do actually want to have some side-effects (imagine a function that reads a config file and then wants to set some of the global variables to the values found there).
Well, bad luck. If you use the subshell syntax you literally can’t do that.
Think of grep as a way to control flow. If one side effect happens, send to stdout one thing. Another side effect, send something else. Then iterate over those outputs.
Edit: It seems I should elaborate.
> Getting anything out of a subshell that isn't from STDOUT is impossible. So you can't define an array in a subshell and then use it outside the subshell, and you can't return an array (or anything that isn't a string) from a subshell. If you only use subshells and want to use any kind of data structure that isn't a string passed from STDOUT, you have to do it globally.
Yes, but that is no problem at all, because that is the way shell scripts work and if you do it in a functional way, where the function has no state, it is great (we a few exceptions).
> And subshells are slow. So nobody uses subshells.
Shell scripts are slow in general, subshells don't make an exception but also don't have a large impact. And people do use subshells.
> If you use Bash for programming, you have to stop thinking in terms of the holier-than-thou software engineer, whose ego believes that a superior, "clean" design makes a superior program. You should embrace globals. You should switch between using or not using the enforcement of set variables or program exit status. You should stop using Bashisms and subtle, obscure language features unless you absolutely have to.
If you use Shell scripts, you should understand that this language has been designed decades ago and that professionals advise to use it just in short scripts to connect binaries.
> Bash is not a "real" programming language, so do not treat it as one. Do not look for hidden features, or try to do things in cute ways that nobody else uses. There is no superior method or hidden knowledge. Just write extremely simple code and understand the quirks of the shell.
That part is mostly okay, but "real" doesn't get the point, as it is a real language, just one with many problems. However, given its superior strength we haven't overcome it yet...
"Superior strength" is probably just a matter taste, however I would really like to read your explanation on why you think so.
Some reasons why POSIX shells are great:
- they are part of POSIX (a Standard which is implemented by multiple OS) and therefore often available
- you can use them to compose programs written in different languages
- you can easily connect the output of one program with the input of another (pipes)
> they are part of POSIX (a Standard which is implemented by multiple OS) and therefore often available
That's not an intrinsic property of Bash.
> - you can use them to compose programs written in different languages
> - you can easily connect the output of one program with the input of another (pipes)
This last point subsumes the previous one. So basically, you're saying Bash is great because it's a shell?
myFunc() { (
#...
) }
So in this case I don't think it makes sense to make a distinction between the two. In essence, I think Bash and the other POSIX shells share most of their greatest strengths and weaknesses.1. Return values of subshells 2. Clean design 3. being a "real" programming language
The only Bash specific part was
> You should stop using Bashisms and subtle, obscure language features unless you absolutely have to.
But in fact, the usage of subshells to limit the scope and subshell return values have nothing to do with Bashisms.
If you use Bash for programming, you have to stop thinking in terms of the holier-than-thou software engineer, whose ego believes that a superior, "clean" design makes a superior program. You should embrace globals. You should switch between using or not using the enforcement of set variables or program exit status. You should stop using Bashisms and subtle, obscure language features unless you absolutely have to.
Bash is not a "real" programming language, so do not treat it as one. Do not look for hidden features, or try to do things in cute ways that nobody else uses. There is no superior method or hidden knowledge. Just write extremely simple code and understand the quirks of the shell.