Hacker News new | past | comments | ask | show | jobs | submit login
Bash Shell Scripting in 10 seconds (aboutlinux.info)
104 points by bennick on Feb 27, 2012 | hide | past | favorite | 32 comments



Linked article is actually a really horrible intro to bash -- at best, it is an OK intro to pre-POSIX bourne shell scripting.

Specifically:

* test and [ ] are fraught with parameter expansion peril. Use [[ ]] instead.

* The author uses single quotes around strings that are demonstrating parameter expansion. Single quotes inhibit parameter expansion, so every one of those examples is wrong.

* select is a better tool than read; case for most of his case-relasted demos.

* Backticks ( ` ` ) are the devil.

At least he points people greg's wiki at the end.


Whoever made the guide is unexperienced in the tasks he writes about. Otherwise he'd know about [[ and ((. Were it an intro for non-bash shells, it would be an acceptable omission. And you're not really explaining how to write conditions if you aren't explaining this:

    # d=abc
    # [ $d -eq 25 ]
    -bash: [: abc: integer expression expected
It also looks to me that aboutlinux.info is in fact just a for-SEO-purposes generated site. Anybody knows more?


Actually POSIX does not recognize double brackets [1]:

"The KornShell-derived conditional command (double bracket [[]]) was removed from the shell command language description in an early proposal. Objections were raised that the real problem is misuse of the test command ( [), and putting it into the shell is the wrong way to fix the problem. Instead, proper documentation and a new shell reserved word ( !) are sufficient."

The entire section on test is full of advice on the proper use of test(1).

[1] http://pubs.opengroup.org/onlinepubs/9699919799/utilities/te...


The article writes about Bash and not about POSIX standardization of test command which omits double brackets.


I replied to a specific comment, not to the article. In particular, nescafe said this was "an OK intro to pre-POSIX bourne shell scripting". I took this to mean that he would provide POSIX-endorsed suggestions. The double brackets, at least, are not "post-POSIX".


Do you know of a better intro? I wasn't even aware of [[ ]] :(



Demystify Bash test and comparison functions

http://news.ycombinator.com/item?id=3639401


What's wrong with using backticks?


They don't nest as well as $()


And backticks can easily slip in when you want to tab or escape, then you can mistake them with a single-quote.

Where they are really the evilest evil is in PHP. Such a dangerous things, nearly invisible!


grumbling guy with beard walks by, mumbles "Here's a dollar kid, get yourself a real font." And walks on...

Unless your shell and editor are displaying in courier, or you use extremely small glyphs (I've seen folks doing terrible things to their font scaling on 100dpi mac screens trying to get more lines on the screen) that should not be a problem. Certainly the Vera Mono font family gets this right; a backtick is quite distinct.


Took longer than 10 seconds, but a helpful introduction nonetheless.


Small nitpick:

for file in .java; do javac $file; done

This will break if the filename contains funky characters like newline or whitespaces. You should prefer using find instead:

find . -name '.java' -exec javac {} \+

Also, I would suggest adding a pragaraph about proper quoting, I usually find it to be an issue beginners struggle with the most.


Although to further nitpick, your proposed substitution doesn't quite do the same thing, since it searches every directory below the pwd, rather than what's in the pwd.

Agreed on quoting.

     for file in *.java; do javac "$file"; done

I'd also like to see something on substitutions which I find useful, like:

     for file in quad_{upper,middle,lower}_{left,centre,right}.dat; do echo "$file"; done
I'd throw in a line or two about the difference between sourcing and executing a shell script, too. Not that this is sh-specific, but I often encounter folks who don't know how they're different, or why, and are perplexed by the behaviour.


Correct about the depth issue. Most find versiosn will present an option to do this, although different versions have different syntaxes (-maxdepth 1 for GNU find, -prune for Solaris).

Agreed on the difference between sourcing and executing. I would say in general it would be beneficial to include a paragraph on which code is executed in the current process and which will fork a new one.


Find is overkill for this.

  for file in *.java; do
     [[ -f $file ]] || continue
     javac "$file"
  done


This would avoid errors on the files with whitespaces, however it will also avoid compiling them. You cannot make the assumption that a file with a whitespace should not be compiled.


Incorrect. Word splitting does not happen in [[ ]] tests. The only reason I had the [[ -f $file ]] || continue is to handle the case where there are no .java files, which will cause the for loop to iterate once with file set to '*.java'. i could have also used nullglob,but chose not to.


It will compile files with whitespaces. That's what [[]] is for.


No it won't, [[ -f $file ]] will fail and `continue` will be executed, moving on to the next iteration of the loop. Think of the different successive values the $file variable will have. At no point, will it hold the full name of the file at once.


I think you're confused. I just tried this in a few shells.

It works in Bash on Cygwin and OS X.

    touch "file with spaces"
    for f in *; do if [[ -f $f ]]; then echo file: $f; fi; done;
This echoes one line for "file with spaces".


What if "*.java" expands to something too large? Or is that only a relevant concern on the command line itself ("Argument list too long" error) and not within a script?


I realize that this is specifically for bash, but this won't work in zsh:

  % for blah in *.java; do echo $blah; done
  zsh: no matches found: *.java


That's just the zsh regex quirk; try quoting *.java.


you need to doublequote $file on your second line:

      [[ -f "$file" ]] || continue


Thank you! I've been looking for a condensed yet thorough overview of bash for quite some time. I use bash only sporadically and I am never successful when googling easy things like how to test for equality of numbers.


I wish I'd found this a long time ago. It took me forever to discover the totally un-googlable but super useful bash variable $?

Dumb, I know, but sometimes the obvious beginner stuff is easy to overlook.


Quoting typo:

  echo $IFS | od -bc
only makes sense as

  echo "$IFS" | od -bc


10?


I suppose that if one were a Bash God, as being any other sort of God, "one day is as a thousand years, and one thousand years is as a day." This implies that you routinely underestimate time by a factor of 365 250. That number of seconds would be about 4.2 days, so to a Bash God, 10 seconds is as 42 days.

42 days is I guess a reasonable estimate for learning Bash if you're really new and coming from Windows -- but perhaps it's a little too much; you could probably get fluent in two weeks if you really focused and already knew the basics of programming.

So the Bash Gods should clearly revise the number down to three seconds.


Yes, I am sure that will take longer than two seconds to read.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: