Hacker News new | past | comments | ask | show | jobs | submit login

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




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

Search: