I use bash and zsh quite a bit in system admin tasks. One thing I find myself needing to do repeatedly is run a command in a loop a given number of times. I'm very well acquainted with cron, but there are often instances where I prefer to run a bash loop inside of a screen session while logging to a file. This gives a lot more control over bleeding edge scripts, and it's easier to "check in" and see what's going on. Here are some simple ways to loop with bash:
# C style for loopfor ((i=0; i<=100; i+=1)); do
# some command
sleep 1
done
# quick loop
for I in 1 2 3; do
echo $I
sleep 1
done
# infinite loop
while [ 1 ]; do
# some repeated command
sleep 60
done
# file loop
for I in `ls *.txt`; do
echo "file $I"
done
4 comments:
Couple things:
1) I'm not sure if it's more portable, but I've always preferred `seq M N` when N-M is large, instead of the ((...)) form.
2) I've seen a lot of people use the "for i in `ls *.txt`" form, and I've not quite understood the appeal: "for i in *.txt" is identical, I'm told more portable, and shorter.
The zsh shell also allows this shortened syntax for single-command loops:
for f (*.txt) echo "file $f"
find . -maxdepth 5 -type f -iname "*.txt" -exec echo {} \;
This does same job like file loop in blog but
* ignores case of filename (-iname)
* recursively with maximum depth of 5 sub dirs (-maxdepth)
* listing only regular files (-type) (f=files, d=dirs)
@steve:
Didn't know about using seq, but that's a nice trick. Backticking ls to glob expand files is indeed unnecessary. Although, there are times when a backtick in a loop context is helpful to operate on the output of an external command, it's overkill in this case.
@dag:
I didn't know that syntax. Thanks for the tip.
@anon:
Yup, find / exec is a really nice combo. Thanks for mentioning it.
Post a Comment