12 ms·
Pure Bash Bible – A collection of pure bash alternatives to external processes
- r3trohack3r 5y agoDylan is an incredible mind - he’s behind KISS Linux and neofetch. KISS is worth looking into as an alternative to Linux From Scratch - I learned a lot with it.
- strzibny 5y agoGreat to see more Bash here. I think for me it comes down to size. If I just need to spin up one server, it's surprisingly easy (as I show in Deployment from Scratch), but of course if I have to do something more complex, I would prefer Ruby/Python. Certainly bookmarking this resource, thanks!
- infogulch 5y agoIt's Bash Month on Hacker News, apparently: My thoughts on writing a Minecraft server from scratch in Bash | https://news.ycombinator.com/item?id=30347501 https://news.ycombinator.com/item?id=30347501 Bash Pitfalls | https://news.ycombinator.com/item?id=30345487 https://news.ycombinator.com/item?id=30345487 Show HN: Toolbox – A framework for modular Bash scripts | https://news.ycombinator.com/item?id=30067708 https://news.ycombinator.com/item?id=30067708 Use Bash Strict Mode | https://news.ycombinator.com/item?id=30217719 https://news.ycombinator.com/item?id=30217719 A Wordle clone in 50 lines of Bash | https://news.ycombinator.com/item?id=30174112 https://news.ycombinator.com/item?id=30174112
- krnlpnc 5y agoI've been sensing a stigma against shell scripting increasingly over the past decade. It's nice to see bash being used in creative and elaborate ways like this.
- AceJohnny2 5y agoThe stigma is well deserved and I will enthusiastically spread it. Bash should be considered an esoteric programming language. Shell Programming Considered Harmful. It's hard to program, and easy to make mistakes in. It should be left as a tool of last resort. (that said, I understand the appeal of doing weird things with it, like the Minecraft server, for the same reason other esoteric programming languages have appeal)
- asdff 5y agoWhat is so hard about it? It feels like python but with an even more english language like syntax, and the man files can be like tomes of knowledge. 'head file.txt' is a heck of a lot easier to wrap your own head around than reading something into an object and calling head on it. Python programmers today would probably import pandas for that.
- scubbo 5y agoNot the person you replied to, but - yes, `head file.txt` is perfectly reasonable, as are a few other use-cases like `grep`/`sed`-ing. But when you go beyond "processing streams of lines of text" and start having to introduce conditionals, maps, or functions, the syntax is (for me, at least) opaque and easy to make mistakes in.
- marginalia_nu 5y agoIsn't that also a case against learning new programming languages?
- vore 5y agoI think bash has a lot of gotchas due to its original purpose, and it's definitely more error-prone to write bash scripts than to e.g. write Python scripts, so that should be a consideration. Ideally we should all try to more programming languages that are harder for us to shoot ourselves in the foot with, rather than easier ;-)
- atarian 5y agoYeah it gets bashed a lot.
- einpoklum 5y agoYet we continue to use it unabashed.
- usrbinbash 5y agoThe stigma is not against shell scripting, the stigma is against using shell scripting for things and in settings it wasn't intended for. Don't get me wrong, I have nothing against fun and creative projects. If someone wants to script something complicated in bash for the lulz, the challenge, to learn something, or just to show off bash-skills, I'm all for it. What I am against, is when I get asked to debug a 2000 LOC system used in production that was thrown together in bash, waste 2 days on it, only to end up doing what should have been done in the first place, and rewrite the damn thing in 200 lines of Python or 400 lines of Go. It can, and should, be used to automate some things, string some commands together, make certain tasks easier. I use and write bash scripts in my daily work, and make my life easier with it. But there comes a point, and that is sooner rather than later, when something should no longer be written in bash, but in a language that wasn't designed primarily as a command line interpreter. Can I make large complicated systems in bash? Sure. Can I carve the handle of a hammer so that it can be used as a screwdriver? I'm sure someone more skilled in woodworking than me could do it. But sometimes the question isn't if it can be done, but if it should.
- dspillett 5y agoThere has always been stigma against shell programming, not shell scripting, and I think that more-or-less is still the case. It isn't so much anti-bash stigma as, using a less than ideal tool for the job being a smell that'll cost you to fix later. Shell scripts to automate processes with other tools is exactly what they are designed for, and adding in other logic and loops is fine too, but if you are setting out to create what would be considered a full program rather than an automated task you should definitely consider alternatives (of which there are several suitable choices) that usually end up being easier to maintain. It used to be that the main alternative was perl, but frankly that was/is no better (IMO much worse) than bash for encouraging the generation write-only (difficult to maintain) code. Python is often a good option, and I've seen node used, though these don't have the ubiquity that sh/bash does (or perl used to have) which is one advantage of bash: it is almost everywhere, even Windows these days (or stick with core posix sh and you'll find support a little wider again), though maybe without some of the supporting externals which is when tricks like these come in. If you are writing some simple automation, or maybe slightly less simple, then bash is fine as a go-to, but if you are setting out to write something complex bash is a bad choice unless compatibility with many environments you can't dictate have another interpreter present is a non-negotiable requirement. There is the grey area when a script, or collection of scripts, becomes a larger program/environment over time. Sometimes the effort to rewrite (and fully test) in another environment is not worth the small benefit of doing so, and is therefore a bad use of developer/admin time that could be used elsewhere, particularly when high performance is not an important feature. Though if you find yourself with a lot of bash script, do yourself (and your later replacement when you've moved on to newer projects) a massive favour and make sure it is well documented even if that is only in in-script comments.
- tomcam 5y agoAwesome that it was made free on github. Of course I donated.
- jteppinette 5y agoI’m sorry, but I almost spit my drink out at how unreadable the very first example is. trim_string() { # Usage: trim_string " example string " : "${1#"${1%%[![:space:]]*}"}" : "${_%"${_##*[![:space:]]}"}" printf '%s\n' "$_" }
- jamil7 5y agoYeah that’s pretty wild. This resource pops up here a bit and it’s cool but there’s always a point where I’m like why would I do this in Bash and not Python/Ruby or something else.
- adhesive_wombat 5y agoI have found my life has improved where as soon as I can't find the answer to a "wtf how do I do this trivial in shell" question after a cursory search, it's a good time to stop, and seriously consider Python (or Perl, ok, ok). Sometimes, it's genuinely better to plug on in shell (e.g. if you are just calling other scripts and chaining stuff), but, especially if you want some less-magical string or list manipulations, often Python/Perl will provide a more readable, more maintainable, more _testable_ script. YMMV with Perl.
- deleted 5y ago[deleted]
- mttjj 5y agoI mean, does it really need to be readable? I kind of took this site to be “here’s some snippets of code that you can use in your scripts to use instead of calling an external process.” Which means to me, I’m going to copy/paste this function into my script, call the function (since it’s structured as one), and never think about it again. “Learn how to write routines like this and make them readable” seems like it’s not the point of this “Bible”. I’m not against readable code by any means (maybe there’s even a cleaner way to write this) but it seemed inconsequential in my opinion.
- aloisdg 5y ago
- jrm4 5y agoAs someone who is genuinely a fan of stupid pointless hacks, like Turing Completeness with CSS or Minecraft or whatnot, in my opinion this is definitely the stupidest. Kudos. The entire point of Bash/Shell scripting is (or darn it, ought to be) to use it to string together OTHER programs to get stuff done. "Pure Bash" to me is like a bar of soap that never gets wet.
- jayceedenton 5y agoTo be fair, when writing scripts it's easy to fall foul of differences between GNU and BSD tools, or using an external tool that isn't available by default on some systems. Pure bash solutions avoid these problems, and can be just as simple as (or simpler than) an alternative that use external tools.
- wink 5y agoUntil you're happy you solved it in a nice way and then learn that your script will run on some ancient RHEL with bash 3 ;)
- xelxebar 5y ago> The entire point... https://en.wikipedia.org/wiki/The_purpose_of_a_system_is_what_it_does https://en.wikipedia.org/wiki/The_purpose_of_a_system_is_wha... Prescriptivism is perhaps helpful when starting out on a project and you need to prune down a vast tree of possibilities, but once you already have a thing, prescriptivist declarations are pretty impotent at helping you understand how that thing works. If your bash script has some tight loop, calling out to external tools can incur a huge performance overhead. Rewriting in bash can aleviate that. How do you re-write it in bash? Well... this article provides good fodder for thought! > like a bar of soap that never gets wet. Here are some uses of soap that would be hampered by it getting wet: - Make-shift lubricant on that sticky cabinet drawer - Draw temporary markings, like a crayon - Potpourri alternative - Fragrant seal on your letters - Deterrent to puppies chewing on your chair legs
- chasil 5y ago
- ChrisArchitect 5y agoPlenty of previous discussion: 1 year ago https://news.ycombinator.com/item?id=24827360 https://news.ycombinator.com/item?id=24827360 2 years ago https://news.ycombinator.com/item?id=21013150 https://news.ycombinator.com/item?id=21013150
- woudsma 5y agoNice to see that the author uses Shellcheck. There is a very nice Shellcheck VS Code extension that links examples of good/bad practices when writing Bash. I can definitely recommend using it if you’re writing Bash scripts!
- deleted 5y ago[deleted]
- cferr 5y agoAnother way to touch a file: cp /dev/null file Test if a port is listening without telnet: echo > /dev/tcp/address/port && echo Yes || echo No That's not actually a file. It's just a path Bash recognizes and is the interface to socket functionality. udp works too.
- IncRnd 5y ago> Another way to touch a file: cp /dev/null file That destroys a file, making it 0 bytes. It doesn't touch a file, not at all.
- _kst_ 5y agoAnd if "file" is the name of an existing directory, it creates an empty file called "file/null". "touch" exists for a reason.
- cferr 5y agoIf the file does not exist, it creates an empty file. That is what most people use touch for.
- deleted 5y ago[deleted]
- IncRnd 5y agoThat's one use case. The actual use case touch was designed for was to update the timestamp of a file. This is a huge case for developers, since timestamps are used in dependency resolution of partial compilation. [1] [1] https://man7.org/linux/man-pages/man1/touch.1.html https://man7.org/linux/man-pages/man1/touch.1.html NAME touch - change file timestamps DESCRIPTION Update the access and modification times of each FILE to the current time.
- xiaq 5y agoIf you're interested in a shell that allows to trim a string without decoding the following: trim_string() { # Usage: trim_string " example string " : "${1#"${1%%[![:space:]]*}"}" : "${_%"${_##*[![:space:]]}"}" printf '%s\n' "$_" } You may be interested in Elvish (https://elv.sh https://elv.sh), which simply has a builtin function for trimming strings: https://elv.sh/ref/str.html#str:trim-space https://elv.sh/ref/str.html#str:trim-space
- chasil 5y agoIn a POSIX shell, I would do it like this: trim_string () ( x=${1%[:space:]} return ${x#[:space:]} ) Note the use of a subshell ( instead of command grouping { because POSIX shells do not have local function variables. At least, I think that would work. On Windows, forking is expensive, so I wouldn't do it this way.
- nomel 5y agoRelated, here's a complexity vs effort graph that I made for our company wiki: https://i.imgur.com/sGPPOhn.jpeg https://i.imgur.com/sGPPOhn.jpeg
- dncornholio 5y agoAfter reading that function, I know why I stay the heck away from bash programming.
- rossy 5y agoThese might make your bash scripts a bit faster in Linux, but they will make them a lot faster in Cygwin and MSYS bash in Windows, where process spawning is very slow. Seriously, if there's even a chance of someone running your bash script in Windows (you might be surprised - every bash.exe is either Cygwin or MSYS, including the one that comes with Git for Windows,) your Windows users will thank you for using pure bash instead of external commands.
- kwertyoowiyop 5y agoI hope to never read or even use such code. I’ll install as many versions of Python as it takes to avoid this fate.
- frazbin 5y agoThe manual is pretty good too https://www.gnu.org/software/bash/manual/bash.html https://www.gnu.org/software/bash/manual/bash.html
- ilyash 5y agoNice... but how you fix the way something fundamental as the way `if` works in bash? Each `if` is a bomb. `if grep -q ...;then ...;else ...;fi`. Two branches for three possible exit codes. Given a long script and big amount of output, you will miss the error message such as "file not found" and the execution will peacefully continue into the else branch. Things like the above motivated me to create Next Generation Shell. Edit: hint - yes branch, no branch, exception. More about motivation: https://ilya-sher.org/2020/10/31/bash-or-python-the-square-pegs-and-a-round-hole-situation/ https://ilya-sher.org/2020/10/31/bash-or-python-the-square-p... Project: https://github.com/ngs-lang/ngs https://github.com/ngs-lang/ngs
- usrbinbash 5y agoUse #!/usr/bin/env bash instead of #!/bin/bash. The former searches the user's PATH to find the bash binary. The latter assumes it is always installed to /bin/ which can cause issues. And the former assumes that `env` is installed in `/usr/bin`, so I am trading one assumption for another.
- fuzzybear3965 5y agoMaybe I shouldn't pick a battle with someone that has that handle . But, in all seriousness, you're right - you're making a trade. The question is which side of the trade is more portable. I use NixOS which doesn't have bash in /bin. So, I've had to ask people on my team to replace the hashbang. The /usr/bin/env hashbang has yet to fail on any machine so, anecdotally, it seems more portable.
- usrbinbash 5y agoIf something is portable to every *nix system which uses the Filesystem Hierarchie Standard (FHS), it's portable enough for every system I ever encountered or worked with. This isn't me ranting against systems with new ideas about file system layout, this is just me being pragmatic: When it works on all my work-, private- and production-machines, I see no reason to run an extra binary in front of all my shellscripts.
- fuzzybear3965 5y agoIf it doesn't support any of your users/co-workers then there's no need. But, there's nothing requiring the enforcement of the FHS in the linux kernel, so, generally, you can't take it's conformance for granted. If something works for X% of people and a trivial change makes it work for Y% of people (Y > X) then I advocate for making that trivial change.
- xvilka 5y agoThere's interesting cross-platform "shell" that compiles to either Bash or cmd (bat) - Batsh[1]. [1] https://github.com/batsh-dev-team/Batsh https://github.com/batsh-dev-team/Batsh