There is a general problem in the fact that a radical evolution of glue languages wouldn't be popular because devs rather use Python, and small evolutions wouldn't be popular (ie. zsh), because they end up being confusing (since they're still close to Bash) and not bringing significant advantages.
I'm curious why there haven't been attempts to write a modern glue language (mind that languages like Python don't fit this class). I guess that Powershell (which I don't know, though) has been the only attempt.
I’m aware that ZSH has been the default shell since Catalina.
Started using fish a month ago and really liking it.
I think being the de-facto default on Linux as part of "GNU plus Linux" has more to do with it.
Like aliases but they expand in-place, so auto completion friendly, easily modifiable, etc. Love them
$ abbr s sudo
$ s<space> -> sudo
This is kind of a good example of what I meant when people conflate "bash" with "shell".
As for your larger point: I kind of agree, but I think what zsh offers is the advantages of shell scripts with compatibility with existing scripts while still improving on it. That said, I believe oil also offers compatibility, but I haven't had the chance to look deeply in to it; just haven't had the time, and wanted to wait until it's stable (maybe it is now?)
Perl was initially invented as the "modern glue language" to replace shell. It's fallen a bit out of fashion these days though, and to be honest I never cared all that much for Perl myself either. Raku looks nice though. TCL also works well as a kind of "glue language", although it has some really odd behaviour at times due to everything being a string and I know some people hate it with a passion, but it always worked fairly well for me. But that has also fallen out of fashion.
I've also been told PowerShell is actually quite nice and has interesting concepts (and now also open source, and you can run it on e.g. Linux), but I could never get over the verbosity of it all. I'm an old unix greybeard and I want my obscure abbreviations dammit!
It's a little more wordy if you're use to C or Bash. But hands down it's one of my favorite languages for slicing dicing data. No need for 3rd party libraries or binaries. No need to learn a bunch of weird awk/jq syntax which is only useful for those two tools (yay, lets learn 3 language instead one?). Plus, most of the structure translates over to C#, and you can integrate C# code directly into your POSH code if desired, as well as access pretty much any low level C# methods directly.
Working with strings? Pretty much any/every tool you could want to slice and dice strings.
The POSH REPL is amazing. You have far more flexibility around interacting with the command line than you do with Python. It's both a shell and a true language. As with any language, there are ISMs, but far fewer footguns than any other language I've spun up.
Cross platform as well with 6.0+
Intellisense ON the commandline (did I mention the awesome REPL?). Hands down one of the best built-in parameter/args/help parsing I've encountered across any language. Debugging? Amazing in vscode. And can be done strictly from the commandline as well (dynamic breakpoints? You've got it, drop you right into your catch block with an interactive shell so you can see the current status of any/all variables and manipulate them live and resume if desired)
Okay, I'm done shilling for POSH. It's hands down one of my favorite shells/languages for doing POC work, or writing utility functions. Treat it more like Python than bash. But realize that you can easily use that Pythonic-esque code right inside your shell.
The nice thing with Powershell is that it's not verbose, but the arcane abbreviations are actually quite a bit easier to remember and discover than bash. What mixes people up is that in documented examples and reusable scripts, it makes sense to use the full, canonical name, which looks aesthetically different coming from a Unix background.
Here's what it might actually look like to check a JSON file that has an array of file metadata objects, and delete the ones that have been processed (this includes one user-defined alias, cfj, for "ConvertFrom-Json"):
gc queue.json | cfj | where status -eq processed | ri
That seems pretty NON-verbose to me, equivalent to how you'd approach this in bash. Do you have jq installed? If you do, perhaps: jq '.[] | select(.status == "processed")' queue.yaml | xargs rm
If you don't have jq I think this gets much longer and is either really brittle (you're doing some kind of adhoc parsing that's terrible) or really heavyweight (like pulling in a pure bash JSON library--they exist) or you're using a one-liner from another programming language (Ruby, Python, something). Or maybe you'd complain to whatever was writing 'queue.json' and ask for a friendlier format, like something terrible and one-off you invented because it's easy to "parse" with awk?).It's even better if you're dealing with network resources:
$api = https://api/
irm $api/queue.json | ?{ $_.status -eq processed } | `
%{ irm -M Delete $api/files/$_.file }
That shows off another alias of Where-Object how you do a foreach loop in
a pipeline. And bash: api=https://api/
curl $api/queue.json | \
jq '.[] | select(.status == "processed") | .file' | \
while read file; do curl -X DELETE "$api/files/$file"; done
What probably makes you think Powershell is verbose is that, although that's how I type Powershell, it's not how I document it. If I were documenting it for someone else's use, or incorporating that pipeline into a script or module, I'd write it like this: Get-Content -Path queue.yaml | ConvertFrom-Json | `
Where-Object -Property status -Eq 'processed' | Remove-Item
So it's not like it's verbose while you're using it, but verbosity is something you can reach for for clarity when it's desirable. Likewise, you can see the consistent relationship between these commands and their aliases: gc -> Get-Content, cfy -> ConvertFrom-Yaml, ri -> Remove-Item. So you have options for how verbose you need to be. I find it's very useful to have a spelled-out version for commands I don't use all the time, like 'Get-EC2Instance', and consistent verbs so I can make reasonable guesses at the command name for things I'm even less familiar with.I didn't want to clutter this with too many examples but I'll reiterate that Powershell is a shell. It invokes your Unix commands just fine. For example, if you forgot what the option to Get-Date is, to get a Unix-style timestamp (it's 'get-date -uf %s' so not exactly hard to use): you can just type 'date +%x'. In the example above, I could have used 'cat' and 'xargs rm' instead of 'gc' and 'ri'. So it's not like you have to buy the whole kit and kaboodle right away, either.
Ten years or so ago the cool kids were using zsh: which is in general a pretty reasonable move, it’s got way more command-line amenities than bash (at least built in).
Today fish is the fucking business: fish is so much more fun as a CLI freak.
But I guess I’ve got enough PTSD around when k8s or it’s proprietary equivalents get stuck that I always wanted to be not only functional but fast in outage-type scenarios that I kept bash as a daily driver.
Writing shell scripts of any kind is godawful, the equivalent python is the code you want to own, but it’s universality is a real selling point, like why I keep half an eye on Perl5 even though I loathe it: it may suck but it’s always there when the klaxon is going off.
The best possible software is useless if it’s not installed.
I was only talking about scripting; I know fish scripting is different, but I have no idea if it's any good. For interactive shells I don't care what people use: it's 100% a personal choice.
You have a level of control over things popping up too
See also <https://apple.stackexchange.com/questions/371997/suppressing...>. I went with the "use an updated brewed Bash" approach, which has been working well. Using `sudo chfn` means you don't need to futz around with editing /etc/shells.
=name will expand to the entry in your PATH. e.g. =ls expands to /usr/bin/ls. So == expands to an executable named =, or rather, it tries to as you probably don't have = in your PATH.
[[ ]] disables expansions (e.g. [[ * = * ]] will work too) so it's not an issue there.
I had to work with Sencha/ExtJS early 2010. It was the same feeling. Yes, it is powerfull, but too much magic happen for something without a clear orientation (at the time, now it is used for data loaded frontend i think). PS i don't understand what it wants me to do.
The language is fine. The interface is now fine, but in 2015 it was the shittiest tty available on modern computers. It's okay since at least early 2021 (when i restarted using windows). I know it should be reasonably better, but i wouldn't trust any PS script written before 2021 to run on my workstation. I run bash scripts i wrote when i started coding.
Still, if you're new to the gig and don't care about free software and commons, you should learn PS (unless you want to work on baremetal or on MC, in this case, bash will be enough).
Bit off-topic, but I worked with ExtJS around the same time, and I found it one of the most confusing development experiences I ever had. "It's so easy, just add this one property to this deeply nested object you're passing to this function!" Thinking back on it, it's a really good example of "simple vs. easy". It didn't help it gave not a peep if you got one of those data structures wrong (capitalisation typo, wrong location, etc.)
Plus in hindsight the whole idea of "OS semantics in your browser!" was never a good one to start with, although that wasn't as obvious to me at the time.
ExtJS (on netbeans with windows server 2004) was always my worst development experience, it was my first internship too. That's probably the reason why it took so long (and a bag of money) for me to try JS, an IDE and developing on windows again (I only used Windows for CTFs and AndroidStudio).
The performance difference was night and day.
The biggest issue with PowerShell is that PowerShell Core is not yet default on Windows 10/11 and Windows Server. That should be Microsofts highest priority for PowerShell.
One reason is that there are thousands of command line tools in the UNIX ecosystem that process text streams and are designed to work with shells like bash. You have much less options when you are processing PowerShell objects.
Note: I think the first thing I tried to do in PowerShell was a script that scanned a directory recursively for files containing a CRC in their name, and then check it, or something along these lines. After several hours of trying, I simply couldn't do it while it was relatively straightforward in bash, even with spaces in file names.
And that's not that I like UNIX shell scripting, in fact I hate it, so many footguns, that's why I wanted to try PowerShell, but it didn't fit my needs.
Not trying to be combative, but learning any new language is going to require some dogfooding and digging in order to be as efficient as something you're already familiar with. I use bash and PowerShell daily. I can't think of any one thing I couldn't do in one or the other. Bash usually requires tying in another tool though. It's not strictly bash at that point. People saying stuff like jq. I rarely find that pre-installed. And if it's your machine, you can just as easily install something that doesn't require you to learn multiple languages (jq is a language).
I here you. I've been there. I'd lazily prod you to give POSH another shake. I've no horse in this race but I think you're missing out if you weren't able to accomplish in POSH what you were able to do in bash.
There is simply no need for the kind of extensive text processing common in Linux because every command returns an object whose fields can be directly referenced. Combined with the ConvertTo-Json command this is incredibly powerful. Honestly it seems like you are attempting to do things in PowerShell the bash way instead of the PowerShell way.
" I think the first thing I tried to do in PowerShell was a script that scanned a directory recursively for files containing a CRC in their name, and then check it"
I wrote a PowerShell script that recursively scanned every filed and folder on our fileshares and wrote the permissions to a file for later indexing.
Or there's some registry hacks to remove the limit from regular paths.
https://learn.microsoft.com/en-us/windows/win32/fileio/maxim...
ls -File | % { $fh = Get-FileHash $_ SHA1; if ($_.Name -match $fh.hash) {$_} }Anyways, it was a long time ago, maybe I will give PowerShell a retry at some point.
Bash, awk, grep et alii don't do OOP. But they are close to the data and are powerful.
Compaints about the notation of these tools (e.g. "line noise") are becoming silly now that we've seen the appearance of some Powershell and Python statements. ^_^
Painful, ugly, unpleasant?
Code that we might deem "beautiful" may not even compile. ^_^
Does the tool do what it needs to do without getting fussy, gobbling RAM, and requiring a small army of maintainers to feed the monster? There is most definitely a place in technology for that kind of sanity.
There is something to be said for a design that doesn't bring with it a brigade of Opinions-As-A-Service proponents.
Any non-trivial notation is going to require learning. There is absolute value in learning. I think of many flexible and effective notations in tooling that has literally been the foundation of modern computing.
Maybe we are in the age of the Mono-Notation Luxury Coder. ^_^
Bash and gawk don't have direct in-language support for OOP, but can be used/abused to do things in an oop manner. aka without in-language support (abstractions/api), takes much more effort to do/understand OOP approach.
Of course Bash is ubiquitous so I use them whenever I can in the company. A golden rule for me is: if it has more than 50 lines then I should probably write in a decent programming language (e.g. Ruby). It makes maintenance so much easier.
And OSH implements almost all of bash
That is, The posix shell spec is missing a lot of reality. It’s not very actively maintained, unfortunately
The canonical example is not having local vars, which basically every shell supports
> It’s not very actively maintained, unfortunately
Because that's how standards works. If there is enough interest a new standard will be made, but right now, bash isn't it.
POSIX was primarily intended a descriptive specification, rather than a prescriptive.
That is, it attempted to document and standardize the common behaviour found on many platforms during the Great Unix Wars, rather than say "hey we thought of this great new thing and released a spec, go implement it!", which is more how, say, web standards work. I does/did have some of that, but it was never the main goal.
These days "whatever Linux does" is the de-facto standard, for better or worse, and the need for POSIX is much less.
* local keyword * 2 or 3 variable expansion tricks (string replacement etc) * pipefail
But with those, I think the spec isn't too bad. I've been writing (imo) high-quality (and shellcheck compliant) shell scripts for a decade, and _always_ try to be as pendantic about being posix compliant where humanly possible. Sometimes things are a _little_ harder (no sarcasm here), but it's really quite doable once you get the hang of it.
You scripts then end up being far more portable, and as stated below, MUCH easier to read. The trick is, to write readable code (which is hard enough for most people, regardless the language anyway :p)
e.g. (a very simple example), and an addition to Shrikant's post, avoid the terse double ampersant 'and' (&&) and double pipe 'or' (||) operators, in normal calls. do e.g. ```sh if ! external_command; then do something with failure fi ``` Rather then `external_command || do something with failure`
These can get up becoming really hard to read once they become longer, where reading a stupid "if" statement is easy to comprehend. Readability over saving number of lines.
One important hint left forgotten, always make sure the last line of your file is `exit 0` or similar. This is more a 'weak' security feature. Prevent people from appending files and executing stuff instead. Gives a known exit point.
Another addition would be to actually favor single quotes for pure strings, and use double quotes where you expect the shell to do something with your string (true for most cases, but there's plenty of strings that benefit from single quotes, and hint the reader what to expect). Also integers should never be quoted (as it would turn then into strings), which shows a 'bad' example in the trace statement, you are now comparing the strings '0' and '1' rather then the number. Best use something easier to read in that case.
One thing I will pick up from this post for sure, is the trace hint, I'm adding that to my scripts, but probably a little more tunable.
```sh set -eu if [ -n "${DEBUG_TRACE_SH:-}" ] && \ [ "${DEBUG_TRACE_SH:-}" != "${DEBUG_TRACE_SH#"$(basename "${0}")"}" ] || \ [ "${DEBUG_TRACE_SH:-}" = 'all' ]; then set -x fi
echo 'Hello World'
exit 0 ``` Though I'll probably just settle for one of those keywords, I like 'all' the best atm. This would run the trace only if this special keyword is given, or if the variable contains the name of the script. I initially had `basename "${0%%.sh}"` but that makes things like `test,test1,test2` impossible, though that only helps if the extension is used ;)
While not needing be part of this list, I personally also always use functions, unless the script really is less then a handful lines, like google's bash-guide, always have a main etc.
In the end though I do disagree writing bash and bashisms. There's plenty of posts about that though; kind of like the whole C++ 'which version to use' discussion, where bash tends to be inconsistent in itself.
Shameless plug: See some of my older stuff here https://gitlab.com/esbs/bootstrap/-/blob/master/docker_boots...
> If I want to run some POSIX-compatible script then I just use `bash scripts.sh`
Shouldn't you be using a shebang?
Why would they use a shebang? `bash script.sh` works perfectly fine. Ever used a terminal?
However, neither Bash nor Fish were created with Composability in mind, which is a show-stopper for me.
IMO don't use Bash if the script is longer than 20 lines and don't use Fish if it's longer than 50. Use Python. If you want to use a proper(!) language use any LISP-Dialect like Babashka, Guile Scheme, Racket, etc. If you need Types have a look at Haskell-Scripting.
EDIT: To clarify, use Fish for its bling-bling capabilities, don't use it for scripting and configuring your machine(s).
Same PS1, aliases, functions, etc. but with a couple of slight variations due to syntax differences
If you're at that spot, don't use shell in the first place but whatever other scripting language your team uses. Well, unless it's "pipe this to that to that", sh has no parallel here
I think fish is quite a bit different in terms of syntax and semantics (I'm not very familiar with it), but zsh is essentially the same as bash except without most of the needless footguns and awkwardness. zsh also has many more advanced features, which you don't need to use (and many people are unaware of them anyway), but will very quickly become useful; in bash all sorts of things require obscure incantations and/or shell pipelines that almost make APL seem obvious in comparison.
In my experience few people understand bash (or POSIX sh) in the first place, partly because everything is so difficult and full of caveats. Half my professional shell scripting experience on the job is fixing other people's scripts. So might as well use something that doesn't accidentally introduce bugs every other line.
Most – though obviously far from all – scripts tend to be run in environments you control; portability is often overrated and not all that important (except when it is of course). Once upon a time I insisted on POSIX sh, and then I realised that actually, >90% of the scripts I wrote were run just by me or run only in an environment otherwise under my control, and that it made no sense. I still use POSIX sh for some public things I write, when it makes sense, but that's fairly rare.
I think bash is really standing in the way of progress, whether that progress is in the form of fish, zsh, oil shell, or something else, because so many people conflate "shell" with "bash", similar to how people conflate "Google" with "search" or "git" with "GitHub" (to some degree).