Thursday, October 18, 2012

bash while loops and pipes

In bash, if you pipe into a while loop, the while loop is run in a subshell. This means that you're going to be very disappointed if you were hoping to capture data/variables within the loop.

The work around is to not have the pipe there - which is possible through process substitution.

e.g.
echo -e "one\ntwo\nthree" | \
 while read name;
  do val=$name;
  echo $val;
 done;
echo $val
This outputs:
one
two 
three

Notice that the final value "three" is not printed twice as 'val' no longer contains a value.

And the work around:
while read name; 
 do val=$name;
 echo $val;
done < <(echo -e "one\ntwo\nthree")
echo $val
which now outputs:
one
two
three
three
Success! (or, if you're a "Bill and Ted's Bogus Journey" fan - Station!).

Monday, October 8, 2012

Mercurial file patterns

I wanted to add all the scripts in a directory tree to the local Mercurial repository. I was going to do something like this:
> find . -name \*.sh | xargs hg add
Which is nice enough (find and xargs go well together), but you can also do it using just Mercurial using patterns. e.g.
> hg add 'glob:**.sh'
The two most useful patterns (for me) are:
  • '*' match any text in the current directory only
  • '**' match anything in the entire tree
The patterns are much richer than this though; see hg help patterns for more on what's available (including regexes).