yet not full of bad habits like the "defensive bash programming" blog post that was on the front page earlier today.
It's the continuation of http://mywiki.wooledge.org/BashGuide
It's entirely possible to learn improper bash when cobbling stuff together over the years. I've certainly done a few things that I've since found much better alternatives for.
As opposed to improper bash? Get off your high horse.
There is very much a bad way of doing bash. When I first started doing bash scripts, most of them looked like this:
cat file | grep string
cat file | wc
cat file | while read line
Multiple problems there. Then there was my initial attempts at finding files in a directory:
for i in `ls *`
This is when I learned about globbing.
There is enough variance in how things can be done in Bash with varying degrees of effectiveness that Google even has a Shell Style Guide:
https://google.github.io/styleguide/shell.xml
https://google.github.io/styleguide/shell.xml
my fx doesn't render the site properly it's just one huge blob of continuous text. impossible to read. why would they do it as an *.xml?
I'm not so sure it is so useless. Consider when you want to "grep something access.log". Then you want to look at yesterday's so it's "grep something access.log.1". Then you want to look at the log before that, but it's compressed. "gunzip -c access.log.2.gz | grep something". (Ignore zgrep for the moment. Let's say I want to use grep's -A and -B options to show context of the lines that it finds.) To switch between the compressed and uncompressed files, you have to move the filename to a completely different part of the command, which requires more re-typing. You would have been better off starting with so-called "useless" cat. Separate out the concern of "putting a stream into the pipe" from "doing something with the stream". gunzip -c is just one command that might produce output.
This is a WIP (hence why there are drafts and todos). This is being done by the folks at http://mywiki.wooledge.org/BashGuide which is definitely a valuable resource if you're trying to learn Bash and its idiosyncrasies.
Omg a whole 3 months ago???!! This repo is soooooooo stale. Bash is constantly changing every day right? I don't want to learn from an antiquated resource!
This is much needed. We essentially have all this software we deal with daily and many people don't know basic things about it, not just bash or zsh... and that is funny, people install zsh because it's the thing to do, but you see that they don't know why.
Thanks for making this! I wish I had a guide like this when I was starting out. Does anyone know if there is something like this for zsh? I'd imagine there would be a lot of similarities, but some notable differences.
If you are writing functions in Bash, your task is probably sufficiently complex that it would benefit from being written in a language other than Bash.
About 7 years ago I had a job where we supported almost every Unix all the way back to AT&T SVR3 (including OpenServer, UnixWare, HP-UX, AIX, Linux, OSF/1). With the exception of SVR3 every single one had binary packages for Perl 5.
Actually, this is exactly the sort of guide I've been meaning to read, since I'm inclined to take the opposite view.
Too often, I think, my task is probably sufficiently simple that it could be a nice portable obviously-a-script Bash script rather than Python/whatever.
Agreed. Bash (and similar scripts) are particularly useful in tasks involving filesystem and process management, where they offer capabilities that are more complicated in other languages. Functions are a helpful way to organize your use of those capabilities.
Zsh has quite a nice option "auto_cd". If the first word you type doesn't resolve to a command, it tries to change the current working directory to it instead. So just typing ~ will get you to $HOME, and .. will take you up one.
Yes. Although you get it for free with Zsh where it works with any directory you type. Not just the ones you think to make an alias for beforehand. :-)
I love this option. I type "/tmp" when I'm about to create some short-lived scratch files. Those saying "you can just alias that" are missing the point. Where do you stop with the aliases?
Even if that is true, it doesn't mean you should not cleanup and organize the bash you have "today" and will port "tomorrow". In the meantime your bash will be better organized and more maintainable.
I wrote sh for this very reason http://amoffat.github.io/sh/ This lets you use a programming language, instead of a shell language, to solve programming tasks.
Bash functions are very useful when you want to manipulate the state of the shell in some way. That is, you write a function for it and stick that function in your .bash_profile. (Unless ofc an alias would be able to perform the job in which case one should just make an alias instead.)
Beyond that, I have been in many situations where standalone shell scripts make the most sense for a task and in which case bash functions have helped me organize the code such that it is both more readable and also so that I don't have to repeat sections of code multiple times within a single script.
It all comes down to personal experience and preference, I think.
Your point is valid, that bash should be avoided as processes become increasingly complex. But there is still room for bash. How much room depends on what you are trying to do.
Bash is incredibly useful, and I think more people should use it as a cross-platform default scripting language. That said, for the most compatible shell scripting, learn Bourne shell scripting. https://en.wikipedia.org/wiki/Bourne_shell
It drives me nuts when people say this. /bin/sh is not even Bourne in some distros (dash in Debian for instance), and bash is installed everywhere (unless you're running AIX, I think ksh is still default). There are some bash-isms that are good things and people shouldn't be afraid of. I think it is actually counter productive to tell people to write things in other languages if you need more complexity. If you're writing a script I think you should be weighing instead whether or not you should fully automate what you're doing. If you decide that's the case of course bash isn't going to be your go-to tool, but if you're writing a one-off script what's the point of telling people to use a more robust language if you can do the job with bash?
I don't understand why people are so opposed to bash in general when it's so powerful for how straightforward it is.
Dash is Bourne-compatible! And Bash is not installed everywhere. I can think of at least five systems i've used in the past five years that either didn't have Bash, or Bash was not the default shell, and even the path to Bash isn't the same on all systems (since it is technically an add-on). Anyway, I did not say use Bourne for more complexity, I said for more compatibility.
People are opposed to learning yet another tool. But here's the really funny thing about the "use a more robust language" argument: not only do they introduce more dependencies, they can introduce more bugs (due to increased complexity), and are almost always a maintenance headache. The one thing that's easy to maintain after 10 years is a shell script. Perl is a nightmare to maintain after 10 years (mostly due to the lack of good Perl programmers) and awk is just barely better.
Right I was thinking about that after I replied to your comment, that I let my point get away from me. I read so many other comments putting down bash I was pleading my case to them, not you, haha.
I did not realize dash was bourne compatible. Also, I'm curious what systems you've used didn't have bash installed by default, as I haven't used anything in a long long time that didn't have bash.
Solaris, BSD, HPUX, hell even stripped-down Linux installs (though sometimes it exists and is just in a weird path). Occasionally I need to bootstrap an OS installer and they never have Bash.
By default I write Bourne, and if I need the extra complexity/speed/etc i'll switch to Bash, but it's pretty rare that I need to use Bashisms.
Something else to consider is that many embedded Linux systems do not have bash, only sh (aka Bourne shell). It is often easier to use only Bourne shell-isms to get things to work in a cross-target fashion. That said, I prefer bash for most cross platform (as in cross OS platform) tasks that need a simple shell script of some kind.
The main advantage is that it's a smaller dependency. If you don't need the functionality, there's a bigger benefit to being portable. For example, running scripts on a router with embedded linux.
The first few chapters look very good, best of luck with the rest!
In case anyone here is interested in more reading material, I recently wrote a small book about Bash that could be helpful: https://gumroad.com/l/datascience
To make sure it didn't read like a manual, each chapter is an "adventure", where I show how to use only command line tools to answer questions such as: What's the average tip of a NYC cab driver? Is there a correlation between a country's GDP and life expectancy? etc
In hopes that the creator does read this, it looks like a great resource but I can't read the text, my eyes are very strained and I got a headache very quickly.
107 comments
[ 2.9 ms ] story [ 177 ms ] thread[1] http://vim-adventures.com/
I for one am enjoying reading through the informative guide.
Nice job on the author for deploying Prose.io for community editing of the guide.
The irony.
There is very much a bad way of doing bash. When I first started doing bash scripts, most of them looked like this:
cat file | grep string
cat file | wc
cat file | while read line
Multiple problems there. Then there was my initial attempts at finding files in a directory:
for i in `ls *`
This is when I learned about globbing.
There is enough variance in how things can be done in Bash with varying degrees of effectiveness that Google even has a Shell Style Guide: https://google.github.io/styleguide/shell.xml
https://github.com/google/styleguide/blob/gh-pages/shell.xml
Another good resource is http://wiki.bash-hackers.org/.
I use a lot of bash though.
So yes, can anyone provide such a list please?
Too often, I think, my task is probably sufficiently simple that it could be a nice portable obviously-a-script Bash script rather than Python/whatever.
Beyond that, I have been in many situations where standalone shell scripts make the most sense for a task and in which case bash functions have helped me organize the code such that it is both more readable and also so that I don't have to repeat sections of code multiple times within a single script.
It all comes down to personal experience and preference, I think.
Just because you can do something in <pet-language-name-here>, doesn't mean it's best done in <pet-language-name-here>.
I don't understand why people are so opposed to bash in general when it's so powerful for how straightforward it is.
People are opposed to learning yet another tool. But here's the really funny thing about the "use a more robust language" argument: not only do they introduce more dependencies, they can introduce more bugs (due to increased complexity), and are almost always a maintenance headache. The one thing that's easy to maintain after 10 years is a shell script. Perl is a nightmare to maintain after 10 years (mostly due to the lack of good Perl programmers) and awk is just barely better.
I did not realize dash was bourne compatible. Also, I'm curious what systems you've used didn't have bash installed by default, as I haven't used anything in a long long time that didn't have bash.
By default I write Bourne, and if I need the extra complexity/speed/etc i'll switch to Bash, but it's pretty rare that I need to use Bashisms.
In case anyone here is interested in more reading material, I recently wrote a small book about Bash that could be helpful: https://gumroad.com/l/datascience
To make sure it didn't read like a manual, each chapter is an "adventure", where I show how to use only command line tools to answer questions such as: What's the average tip of a NYC cab driver? Is there a correlation between a country's GDP and life expectancy? etc
https://github.com/koalaman/shellcheck
https://github.com/matze/jekyll-ditaa