*nix is friendly, it is just selective in who its friends are" .. is a dot-signature from that era
A manual is a reading experience, a working reference system, and relies on the visual context it is presented in. There are vast differences in the quantitative and qualitative contents of manuals, on the same content! The BASH man page is .. improving ?
Specifically compare an alphabetized list of every option, including "change the preferred shortcut" and "let the sea-water in, thereby killing everyone if you are underwater" .. are right next to each other .. to modern manuals in say, the Python culture. Specifically compare say, huge amounts of text supplied for some obscure option that is not at all needed, to a terse one-liner for something crucial that is used everyday.
The parent comment cheerfully "blames the victim" with implied guilt for "not reading the manual" as if more time and effort on the part of the user, is the answer to the communication problem posed with such a dense and subtle realm.
Last thing in this rant is, that a small interesting article on something specific is an antidote to the largely unsolvable challenge here, so good on that.
When I had to start dealing with bash a lot about 5 years ago I consulted "Greg's Bash Wiki" at https://mywiki.wooledge.org/BashGuide and it pretty comprehensively treats best practices for writing bash scripts. I often go back to consult the guide.
This is an open-source thing. Hardly anyone wants to write documentation that isn’t paid to do so. There’s no glory in it. I first learned Unix on SunOS/Solaris and the man pages were excellent. You could start with “man intro” and learn your way around the entire system from there.
BTW, if you think you’re any good at documentation, open-source needs your help. It’s a great way to contribute.
There actually is glory in it. Many (granted, not all) popular, celebrated open source projects got that way by having a great user experience with intuitive, accessible docs.
I actually think that most programmers (even many very good ones) are simply bad at writing docs. They actually can't do it well. Or it would be a monumental effort for them to do it well.
It really is a different skill set.
Or are these "great programmers" not actually that good at that?
It is correlated (though probably not perfectly) with writing readable code. But that is a different skill from writing useful, correct software. That is, you can write useful, correct software whose code is difficult for others to understand and maintain.
An oddly specific comparison.
I've written literally thousands of lines of shell scripts (maybe even 10k+) across dozens of scripts over the years and I've only really looked at the docs a couple of times. Of course I'm Googling various syntax things that are humanly impossible to remember, but I never once really sat there and combed through all of the docs or even read a book on Bash.
You can't do that with most programming languages.
It may be care free, fun, and effortless for you, but try being on the receiving end of that behavior some time.
RTFM! And if the manual sucks (like the Bash manual), then learn to use another language.
Instead of learning to write shell scripts better, people should learn NOT to write shell scripts, and learn a decent scripting language instead.
You will find that most decent scripting languages like Python are actually a hell of a lot easier to learn and program and maintain than shell scripts.
I wrote it in Bash.
https://www.donhopkins.com/home/catalog/unix-haters/x-window...
(Well that, and installing Solaris.)
https://www.donhopkins.com/home/catalog/unix-haters/slowlari...
#!/bin/sh
# This works...I wonder if it will get me laid
progname="`echo $0 | sed 's:^\./\./:\./:'`"Code can be astonishingly durable.
However, I recently discovered the power of Python’s Fabric scripts, and holy cow... the ability to run functions on multiple computers at the same time based on roles is amazing (even if the “join” syntax is cumbersome as hell).
I think in general, simple system things should be written as scripts. The moment you realize “this is going to take a LOT of scripting” it’s time to look at Python because chances are there’s a module for that.
But on that note, a majority of my current shell scripts are being used on my dev box to improve my day to day. Things like this: https://github.com/nickjj/invoice
It really breaks my heart to see stuff like this pointlessly wasting electricity by running on a computer that has its own "mul" instruction -- like forking off a "bc" and sending it a stream of decimal digits over a pipe just to multiply a number by 100:
echo " > \$$(echo "100 * ${default_hourly}" | bc -l) 100.00 \$${default_hourly} 50 acme"
Don't tell me you prefer writing shell scripts that do simple arithmetic because it's more convenient than using Python.Calling out to awk to do trivial string manipulation may impress you as "amazing" after you've hit the wall trying to convert a string to decimal hours with bash and bc, but do you really enjoy all that noisy cryptic bash syntax with all those carefully orchestrated backslashes, double dollar signs, triple angled brackets, echos and pipes and quotes, nested parens and braces, and mysteriously abbreviated dash-letter parameters, to typing "100 * default_hourly"?
At least Python's "*" operator doesn't require a "-l" parameter to figure out how to multiply a number by 100.
The process id is not your Linux high score. There's no need to run it up by forking so many processes all the time.
> Don't tell me you prefer writing shell scripts that do simple arithmetic because it's more convenient than using Python.
That's not a fair comparison. The code you pasted isn't just doing the calculation. It's dynamically generating a human readable help menu that shows both the input and output of what the script will do. That requires quite a bit more characters and escaping.
The "real" calculation to get the hourly is:
amount="$(echo "${total_hours} * ${hourly_rate}" | bc -l)"
Seems pretty straight forward to me. Plus, that's a really cherry picked example in Python's favor. You should evaluate the whole script's purpose. It's mostly just reading and filtering text output from a file and then performing basic math on the filtered text. Seems like a textbook case to use Bash IMO.You're the one who got to cherry pick the script to use as an example, so don't complain that I cherry picked the most ridiculous line of that code.
Python can generate a human readable help menu with much less trouble.
Tell me one thing about that script that's easier in bash than in Python.
Forking off sed? Python doesn't need to, it has string manipulation. Forking off bc? Python doesn't need to, it has arithmetic.
And why are you using sed regular expressions just to do arithmetic? Now you have two problems!
https://blog.codinghorror.com/regular-expressions-now-you-ha...
Again, look at the Linux kernel and userland source code and give me a ballpark estimate of how many instructions it requires to multiply a number by 100 by forking off bc or sed, instead of executing a single "mul" instruction.
And Python code doesn't require a page of comments to explain why it has to go to so much effort and work around so many pitfalls just to convert a couple of strings to decimal hours.
Why, Python even has named function parameters -- now THAT is TRULY "amazing".
And in the number of keystrokes it took you to write the following comments (and the number of trials and errors it took you to finally get it right), you could have imported a hell of a lot of powerful Python modules, and read a lot of the interactive built-in help documentation about their APIs.
Your time would be much better spent getting used to using Python rather than sed.
to_decimal_hours () {
local hours="${1}"
local minutes="${2}"
# [h: ] uses the "h", ":" or " " character as a split delimiter.
#
# If the first split argument ends with "m", then we're not dealing with
# hours at all, only minutes, so now $1 becomes minutes and we divide by
# 60 because you can't have more than 60 minutes in 1 hour.
#
# Otherwise, we have both hours ($1) and minutes ($2). The hours can be
# taken as is, and like before the minutes get divided by 60.
#
# It's also important to send both the hours and minutes in without a
# space as input, otherwise values like "30m" will end up being "30m "
# which makes $1 no longer end with an "m" and it will incorrectly report
# back 30.00 instead of 0.5.
#
# awk will automatically remove the "h" and "m" characters when it comes
# time to do the addition.
#
# Yep, awk is amazing. I'm just getting used to using it!
awk -F '[h: ]' '{ if ($1 ~ /m$/) printf("%.2f\n", ($1 / 60));
else printf("%.2f\n", $1 + ($2 / 60)) }' <<< "${hours}${minutes}"
}Look, if you want to sit there and rip into a stranger on the internet for open sourcing a Bash script (on their free time) then by all means knock yourself out.
For the record I've written more Python than I have Bash (by a substantial amount). I wrote that script in Bash because it took literally 3 minutes to prototype it on the command line with grep, cut and bc so I spent the extra hour turning it into its current form. It does exactly what I want it to do (nothing less, nothing more).
Also the code is MIT licensed. Free free to fork it, rewrite it in Python, test it on 50+ real invoices, write extensive test coverage, write ~1500+ words of documentation and then make a ~20 minute video showing to use it.
Being open source doesn't magically make your code great or efficient or bug-free or easy and irresistible for millions of eyeballs to examine and audit (in spite of what ESR's fallacious "Linux's Law" might claim), or obligate anyone to complement it or use it or take it and run with it.
https://en.wikipedia.org/wiki/Linus%27s_Law
If you make your code open source, then post links to it in public forums, right after bragging about only reading the language documentation a couple of times, you'd better get over being thin skinned about criticism.
I'm not criticizing your code, or your decision to open source it, or which license you chose, or your pride in only reading the documentation twice, or your decision to cherry pick and share that script as the best example you could come up with of bash's superiority. I'm criticizing your decision to write the code in bash instead of Python.
Can you at least please answer this one simple question: Name one thing about that code that is easier in bash than in Python?
>I've written literally thousands of lines of shell scripts (maybe even 10k+) across dozens of scripts over the years and I've only really looked at the docs a couple of times. Of course I'm Googling various syntax things that are humanly impossible to remember, but I never once really sat there and combed through all of the docs or even read a book on Bash.
At least you admit 1) you've only really looked at the docs a couple of times, and 2) bash syntax things are humanly impossible to remember.
Have you ever written any 10k+ line bash scripts? No, because it doesn't scale (and machine generated configure scripts don't count). I have a 16,078 line Python script in my emacs buffer right now that I wrote over more than a decade (which is just one facet of a big system written in many other languages).
My point (which is just a corollary of JWZ's Law of Software Envelopment and Greenspun's Tenth Rule) is that programs always grow over time, and you never realize how big and complex your programs are going to grow or how far they're going to evolve when you first write them.
So never assume you can get away with using a language that's so lame it has to call out to two other different languages just to perform simple string manipulation and arithmetic.
Good grief, even TCL can perform string manipulation and arithmetic without forking a bunch of new processes.
You should invest more time using languages with docs you can actually read, and with syntax you can actually remember. You might like it.
https://en.wikipedia.org/wiki/Jamie_Zawinski#Principles
>Zawinski's law of software envelopment (also known as Zawinski's law) comments on the phenomenon of software bloating with popular features:
>Every program attempts to expand until it can read mail. Those programs which cannot so expand are replaced by ones which can.
https://en.wikipedia.org/wiki/Greenspun%27s_tenth_rule
>Greenspun's tenth rule of programming is an aphorism in computer programming and especially programming language circles that states:
>Any sufficiently complicated C or Fortran program contains an ad-hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.
It's free of Python dependency hell: easier on the downstream consumers.
Python would be a nice language if it were more like Awk: a single executable with a few satellite files and no goddamned "ecosystem".
https://imgs.xkcd.com/comics/python_environment.png
In all other regards, of course proper data processing in one language is vastly superior to some awkward string chopping through external processes.
> You should invest more time using languages with docs you can actually read, and with syntax you can actually remember. You might like it.
Didn't grandparent say: "I've written more Python than I have Bash (by a substantial amount)".
People who aren't stupid and know other languages still whip out little shell scripts; we should try to understand why that is.
Nobody's running such an old version of Ultrix on their MicroVAX with a big yellow thick wire Ethernet cable and vampire tap and static /etc/hosts file derived from HOSTS.TXT downloaded weekly from SRI-NIC.ARPA without checking certificates for man-in-the-middle attacks and running unencrypted rlogin and telnet demons instead of ssh any more, that they can't easily and securely update Python and install modules.
Also: You think the Python "ecosystem" is goddamned? Remember that bash by its very nature depends on a terribly goddamned inconsistent "ecosystem" consisting of all the essential utilities it requires to do the most elementary of tasks, including awk, sed, dc, cut, grep, yes, and many others, whose locations and apis and features and parameters and behavior and performance vary widely from platform to platform. Bash is much more tightly coupled with the operating system distribution that Python.
While most of those essential features (like cough cough string manipulation and arithmetic rolls eyes, among others) are built into Python or available as standard plug-in modules (like os, system, threading, multiprocessing, pexpect, mmap, readline, Beautiful Soup, SQL Alchemy, json, yaml, etc) that are identical across all platforms.
And most of those Python modules are vastly more efficient than their bash counterparts, because they don't require forking separate processes instead of making local procedure calls, communicating over 1-dimensional pipes instead of shared memory, serializing and deserializing text parameters and data instead of passing pointers to live data structures.
What good is a scripting language these days that doesn't have built-in json and yaml parsers (not to mention a nice way to parse html and talk to databases)? I see so many half-assed bash scripts desperately trying to parse field separated values and process output with regular expressions, grep, cut, awk and sed, by forking off hundreds of ridiculously inefficient processes.
Yes I know there are xpath/jsonpath utilities you can execute from bash scripts that look up elements and keys in XML documents and json dictionaries -- that's my whole point, that there NEEDS to be something like that! God forbid you need to process 150 million records.
And as to what the grandparent poster actually said: I explained in the cousin posting below that I quoted and addressed what he ORIGINALLY said, and then he NINJA-EDITED it after I replied, to substantially change the meaning and remove several ridiculous, indefensible statements.
https://news.ycombinator.com/item?id=19898052
Unless he's just gaslighting and actually MEANT for you and others to mistakenly believe that I was putting words in his mouth (in which case we should expect his radio silence to continue), I'm still waiting for him to acknowledge that fact, and finally reply to the simple straightforward question that he kept avoiding:
Name one thing about that script that's easier to do in bash than in Python.
But I'm not holding my breath. Do you care to chime in with an answer instead?
>People who aren't stupid and know other languages still whip out little shell scripts; we should try to understand why that is.
Well the grandparent's excuse (which he deleted) for whipping out little shell scripts was that he "only really looked at the docs a couple of times". I don't think that's a legitimate excuse, myself, and apparently neither did he, so he ninja-edited it out, instead of admitting it wasn't a good defense of bash to brag about only reading the manual twice.
> The current year is 2019. It's not as if every modern Unix based operating system didn't already include or even require at least one goddamned Python ecosystem.
If you're just talking about Linux, this is kind of true (Fedora's dnf and yum before it are built on Python). But AFAIK Debian/Ubuntu apt-get is written in C/C++ and does not require Python.
Non-Linux unixes like, say, FreeBSD, do not have Python in the base distribution (nor bash). It's available in ports, which might be what you're getting at.
That said, my experience has been that non-Linux "posix" Python is a second class citizen to Python on Linux. Just for example, signal/thread semantics happen to align in a certain nonspecified-by-POSIX way on Linux and differently on FreeBSD. IIRC, FreeBSD delivers nonspecific process signals (e.g., external INT or TERM) to the most recent thread, whereas Linux delivers signals to the oldest thread. Or vice versa, but Python has its own weird signal semantics it tries to impose on top of this that works better on Linux's model than FreeBSD.
As a second example, Python fork+exec invokes close() on every possible integer between N and the file descriptor limit. This is typically tolerable for naive python programs on Linux because the default fd limit is usually 1024. FreeBSD scales the default fd limit with memory, often resulting in a much larger limit (e.g., ulimit -n = 939258 on this 32GB system). For years we have tried to get Python to adopt the closefrom(2) API, which accomplishes the same goal much more cheaply. But because most Python developers are on Linux, they simply don't feel the pain of a subprocess.Popen() taking noticeable fractions of a second.
> Also: You think the Python "ecosystem" is goddamned? Remember that bash by its very nature depends on a terribly goddamned inconsistent "ecosystem" consisting of all the essential utilities it requires to do the most elementary of tasks, including awk, sed, dc, cut, grep, yes, and many others
No disagreement there.
> What good is a scripting language these days that doesn't have built-in json and yaml parsers (not to mention a nice way to parse html and talk to databases)?
jq is a wonderful tool for parsing and manipulating JSON in sh, though it has its limitations. I certainly wouldn't attempt to parse HTML in (ba)sh. I don't encounter YAML very often.
> Name one thing about that script that's easier to do in bash than in Python.
"ls -l"? There are lots of quick and sloppy path manipulation things that are easier to bang out in shell than in Python -- that's why most people use (ba)sh et al as interactive shells, instead of python.
Anyway, Python is powerful, and quite possibly more consistent platform to platform than bash. No disagreement there. I'd also argue it's a much better tool for writing programs that handle adversarial input than bash is. The ways Python differs between platforms are mostly areas bash doesn't attempt to cover at all. And the datastructures available in Python are much more powerful than in bash.
Has anyone tried coding it and creating a locally applied patch?
I posted a link to it next to the sentence that talked about the types of tools I use it for, such as things on my dev box to help me in my day to day.
> Have you ever written any 10k+ line bash scripts? No, because it doesn't scale (and machine generated configure scripts don't count)
I've written a bunch of 1k+ line scripts. They aren't a problem to maintain and a number of them are being actively used and maintained by other people. These are for real production systems too. Some are single files, others are broken up into multiple files.
I haven't personally written a 10k+ line script (the need for that has never happened), but I've seen a number of multiple thousand line scripts out in the wild that are very well maintained and are part of mission critical systems like setting up a PKI realm for a bunch of servers. That PKI script was something like 4,800 total lines of code but it being 10k+ wouldn't have made a difference for the worse.
Shellcheck helps a lot with writing pretty well formed shell scripts. It's a really good linter.
>I've written literally thousands of lines of shell scripts (maybe even 10k+) across dozens of scripts over the years and I've only really looked at the docs a couple of times. Of course I'm Googling various syntax things that are humanly impossible to remember, but I never once really sat there and combed through all of the docs or even read a book on Bash.
Only really looking at the docs a couple times isn't something to brag about, and doing that doesn't make bash good.
Nor is it good for languages to be designed so you don't have to read the manual (or else you get COBOL or HyperTalk, and then you still have to read the manual).
Nor is it good for languages to have syntax things that are humanly impossible to remember.
All those claims you deleted actually support my point about bash being terribly inferior to Python (whose syntax is extremely simple and easy to learn and remember and most importantly read, and it even has built-in interactive "help" documentation), which is why I quoted what you originally said in the first place.
Again, what is it about that script you offered as an example that is easier, more elegant, or more maintainable and understandable to do in bash than in Python?
If you don't have an answer to that, can you show me any other bash code that was better off written in bash than in Python? And explain how it's better, please.
Knowing the basics of shell scripting is not optional. As a dev on a unix system, it's just a question of time before you have to read and tweak other people's scripts.
You may think you're clever enough to sneak out a little one-liner that nobody will notice, but all too often you underestimate the task, and it blossoms into a big messy shart script that other people have to deal with.
I often describe my bash book as an attempt to carefully demystify the man page so that you can approach it with confidence.
http://tldp.org/guides.html#abs
Beginners might prefer the Bash Guide for Beginners:
http://tldp.org/guides.html#bbg
The Bash manual page is concise because it is a Unix manual page. Unix manual pages are supposed to be concise, because they are meant to be reference documents, not tutorials. In the GNU project, this is what the Info documentation is for. However, the bash project has elected not to maintain such a document, so the above documents from TLDP (The Linux Documentation Project) are the next best thing.
https://www.worldcat.org/title/from-bash-to-zshell-conquerin...
https://www.worldcat.org/title/learning-the-unix-operating-s...
Checking zsh by comparison: 6 pages, though a long "SEE ALSO" list with 10 zsh-specific entries, totalling 374 pages in all:
for zsh in zsh zshbuiltins zshcompwid zshcompsys zshcompctl \
zshexpn zshmisc zshmodules zshoptions zshparam zshzle; do\
man $zsh | pr | grep 'Page *[0-9][0-9]*$' | tail -1; \
done | awk '{tot+=$NF}; END{print tot}'I'm aware that generating postscript is possible, and results in fewer pages. But that doesn't readily permit comparisons with simple shell tools.
(The output is decidedly pretty though.)
Actually, I don't want to do that either.
What I really want to do is use a Python script instead. :3
Then you have Xonsh, but in my opinion, switching between the two contexts, shell and python, at each part of a command was too difficult. I was totally lost even at writing very basic commands.