7 ms·
I've grown rather fond of bash in my current role. I work mainly on developer tools and CI pipelines, both of which mean gluing together lots of different CLI t
by hamandcheese 2y ago
I've grown rather fond of bash in my current role. I work mainly on developer tools and CI pipelines, both of which mean gluing together lots of different CLI tools. When it comes to this kind of work I think it is quite hard to beat the expressiveness of shell scripting. I say this as a former hater of bash and its syntax.
Much credit to copilot and shellcheck, which have made complex bash ever the more write-only language than it already was.
- chasil 2y agoBash actually has more warts than competing shells because of its historic stance. My bugbear is that "alias p=printf" works well in any POSIX shell script, including bash when it is invoked as #!/bin/sh - but when called as #!/bin/bash, the alias (used in a script) fails with an error. While the Korn shell managed to evolve and comply with the POSIX standard, bash decided to split the personality, so one solution to the above alias failure is to toggle POSIX mode. Bash was forced to do this, to keep a decade of shell scrips that were written for it working. Pity. The standard for the POSIX shell looked very hard at Korn, and credits it. Bash is not mentioned.
- mort96 2y agoHuh, why wouldn't that alias work?
- photon-torpedo 2y agoGood question. Something to do with interactive mode? $ cat l.sh alias l=ls l $ sh l.sh file1 file2 l.sh $ bash l.sh l.sh: line 2: l: command not found $ bash -i l.sh file1 file2 l.sh Edit: Ah yes, the man page says so. > Aliases are not expanded when the shell is not interactive, unless the expand_aliases shell option is set using shopt
- mort96 2y agoThanks, I had no idea. I guess I've never used aliases in scripts, but I would've assumed that they'd just work the same as in interactive mode. Good to know.
- RhysU 2y agoWhy use an alias in a script? Or in general? Functions work everywhere.
- sudahtigabulan 2y agoI suppose aliases predated functions. Can't find a reference to support that, though. Just a possible reason. BTW aliases come from csh, and there they support arguments, which makes them similar to functions.
- oguz-ismail 2y agoAliases are like C macros $ alias foo='seq 3 | ' $ foo cat 1 2 3 Functions are functions
- RhysU 2y agoSo then use $variables for evil syntactic tricks? That works everywhere. Functions where hygiene counts? Aliases never?
- oguz-ismail 2y ago>use $variables for evil syntactic tricks Can't do that without eval, which is another can of worms. Aliases are fine
- metadat 2y agoFunctions don't work everywhere. Bash functions only work in the current shell context unless exported via an `export -f myfun' statement in between the function declaration and downstream sub-shell usage. Working example: pzoppin() { printf 'echo is for torrent scene n00bs from %s\n' "$*" trap "printf '%s\n' <<< \"$*\"" RETURN EXIT SIGINT SIGTERM } export -f pzoppin echo -e 'irc\0mamas donuts\0starseeds' \ | xargs -0 -n 1 -I {} /usr/bin/env bash -c ' echo hi pzoppin "$*" echo byee ' _ {} The above will fail miserably without the magic incantation: `export -f pzoppin' Why'd they design an otherwise perfectly usable, mapless language without default c-style global functions? :)
- BoingBoomTschak 2y agoIndeed, here are two lines atop my "util.sh" to regularize some strange non-conformant behaviours: [ "${BASH:-}" ] && shopt -s expand_aliases [ "${ZSH_VERSION:-}" ] && setopt SH_WORD_SPLIT
- deleted 2y ago[deleted]
- cduzz 2y agoI typically just give up on weird corners of shell when I find an working version of the same. For instance -- why would you use "alias" when you can make a function? The syntax is a little weird with functions, but it's a lot more clear what's going on. The same goes for "test" vs the seeming magic of [ where it seems like [ is language syntax (it's a single character!) when in fact ... it's just another executable that communicates with logic evaluation like anything else (like grep or false).
- alganet 2y agoThere are many reasons. 1. Aliases can work with the callee scope. alias MY_VAR_MODIFIER='local foo=bar' MY_VAR_MODIFIER () { local foo=bar; } Calling the alias by the name will set the callee's variable foo, while calling the function does nothing (local foo is local to the function and never leaves scope). It also works similarly for working with the set ($@). You can do `set --` stuff and it works on the scope of the callee.] Aliases on most shells also don't need to be fully valid _before_ expansion. You can alias a compound command: alias foreach='for EACH' foreach in $MYVAR #perfectly valid for most shells. Only ksh93 will complain about it, it requires aliases to be complete valid shell programs. Finally, alias calls don't appear in xtrace (set -x). Only the final expansion will appear. TL;DR aliases in scripts work a lot like macros.
- IshKebab 2y agoGluing together tools with shell scripts is a significant cause of CI failures in my experience. There's no reason to do it. Use a real language - at least Python, but my preference is Deno because it's not dog slow and you don't have to deal with venv.
- Spivak 2y agoI mean I guess but what's your plan when your script is just a bunch of subprocess.run calls? I promise you it won't be any less brittle.
- tom_ 2y agoThe subprocess.run args argument is a list of strings, not a single string with whitespace-delimited parts, so you're all good quotingwise. This is now effortlessly a lot better than what you get with bash in terms of how brittle things are! Supply check=True and the script will barf on subprocess failure. Another useful upgrade.
- KingMob 2y agosubprocess.run() will happily accept a single string, though, so you may still inadvertently run into the issue anyway.
- deleted 2y ago[deleted]
- iamjackg 2y agoTake a look at https://sh.readthedocs.io/en/latest/ https://sh.readthedocs.io/en/latest/ for a very usable solution to easily run other processes in Python. It has made my life a lot easier whenever I've had to migrate a shell script to Python.
- IshKebab 2y agoI promise it will! It will handle weird filenames properly for example. But realistically it's rarely that simple and even when it starts that simple it will grow to not be. The downvotes are a very disappointing attitude.
- eadmund 2y ago> I've grown rather fond of bash in my current role. I work mainly on developer tools and CI pipelines, both of which mean gluing together lots of different CLI tools. When it comes to this kind of work I think it is quite hard to beat the expressiveness of shell scripting. Every time I have to express logic in YAML, I miss shell. Shell’s really not great, and it could be improved upon (my vote? Tcl), but it’s so much better than where the industry is these days.
- hollerith 2y agoYou can't use a shell script or a TCL script to generate the YAML file?
- eadmund 2y agoSure, you can generate the YAML file, but it’s not generally possible to trigger that from the system which wants the YAML file, and you don’t get to integrate with the system’s configuration. Often these systems honestly think that their approach of logic-templated YAML is preferable to a script — for example Helm’s templated Kubernetes YAML.
- hamandcheese 2y agoFew things grind my gears worse than _templated_ yaml. It equivalent of building up a json object using only string concatenation. Most people would raise their eyebrows at that, yet templates yaml is seen as very normal. I think in part it's a skills mismatch - a lot of devops/sysadmin type folks I encounter, while very talented, are not prolific coders. So code-forward solutions like jsonnet, starlark, dhall, nix, etc. are rather unfamiliar familiar. It doesn't help that all but one of those languages mentioned are odd little functional languages, increasing the familiarity gap even further.
- hollerith 2y agoThanks.