Short answer: those aren't separate invocations; you're only running svn update
once.
(You can test that by running the function under set -x
, which makes bash print every command as it is run: set -x; svn_update_all; set +x
)
If you really want to run svn
multiple times (and you're certain you will never have spaces in your paths), you can just drop the quotes around $repos
:
svn_update_all ()
{
repos=`find . -name '.svn'`
for i in $repos
do
svn update `dirname $i`
echo
done
}
Here's the deal with for
loops. bash(1)
says:
for name [ [ in [ word ... ] ] ; ] do list ; done
The list of words following in is expanded, generating a list of
items. The variable name is set to each element of this list in
turn, and list is executed each time.
So the contents of the for
block runs once for each word after in
. Here's an example:
count=0
for num in one two three; do
do
let count++
echo "loop $count: '$num'"
done
loop 1: 'one'
loop 2: 'two'
loop 3: 'three'
But a quoted string is taken as a single word. This is basically what's happening in your script:
count=0
for num in "one two three"; do
let count++
echo "loop $count: '$num'"
done
loop 1: 'one two three'
Remove the quotes and $repos
gets split into separate words again, and then svn update
gets run once for each repo, as you expected.
Note well, though: this will break if you ever have a path that has spaces in it.
The simplest way to handle paths that might have spaces is to pipe the output of find
into the read
builtin command:
find . -name '.svn' | while read i
do
svn update `dirname $i`
echo
done
The safest way is to use find
's -exec
or -execdir
actions, so you don't have to worry about bash
splitting up filenames:
# print the repo dir, then run "svn update" in it
find . -name '.svn' -printf '%h: ' -execdir svn update \;
./mpc: Updating '.':
U trunk/src/pow.c
U trunk/tests/pow.dat
U trunk/m4/mpc.m4
Updated to revision 1455.
./mpfr: Updating '.':
[etc]