Getting Loopy with Bash: using for loops

July 6th, 2009 by Shawn Powers in

Your rating: None Average: 3.7 (9 votes)

Download in .ogv format
__________________________
Shawn Powers is an Associate Editor for Linux Journal. You might find him chatting on the IRC channel, or Twitter


Special Magazine Offer -- Free Gift with Subscription
Receive a free digital copy of Linux Journal's System Administration Special Edition as well as instant online access to current and past issues. CLICK HERE for offer

Linux Journal: delivering readers the advice and inspiration they need to get the most out of their Linux systems since 1994.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Guy Stalnaker's picture

<grumble>

On July 7th, 2009 Guy Stalnaker (not verified) says:

And no sooner to I post here than I find the answer on another site, ShellGeek (imagine that). So, thanks anyway.

Guy

Guy Stalnaker's picture

Using for at the prompt

On July 7th, 2009 Guy Stalnaker (not verified) says:

I was trying to come up with a way, using for, to run an executable on the output of the ls command in a directory. That is, to have the output of ls be the input to a command:

#> for m in `ls`; do echo $m; done

This works ONLY if the file names in the directory have no spaces, e.g.,

~>ls
autosave Documents Music
bin emerald-themes
Desktop logs.05182008.sp.zip
doc man

But if the filename is a multi-word name with spaces, the for construct assigns to m the individual words and the echo output breaks the filename across separate lines. I suppose this has more to do with how ls outputs, but I cannot find an ls option (not -Q nor -1 nor -x) that seems to get the for construct to 'think' that the filenames output by ls are legitimate if they have spaces (if that makes any sense).

I have found a way to use find's -exec or -print0 with xargs to do what I wanted to do, but I was curious if any of you gurus at linux journal can come up with a way of using for on the command line:

for x in '{command with output}'; do {command on output} $x; done

Anonymous's picture

for m in `ls`;do command

On July 8th, 2009 Anonymous (not verified) says:

for m in `ls`;do command "$m";done

putting $m inside " marks causes $m to be a single argument. I do this all the time when I used Cygwin on Windows (at work).

--
John

pschmitt52's picture

re: it should be noted though

On July 7th, 2009 pschmitt52 (not verified) says:

Isn't this the LINUX Journal after all? :)

slacker's picture

it should be noted though

On July 7th, 2009 slacker (not verified) says:

it should be noted though that calling seq makes it less portable as you wont likely find seq on many flavors of unix... granted you can argue that you wont find bash either but hey, just sayin.

thogarty's picture

target :)

On July 7th, 2009 thogarty says:

That looks like a Target ball in the intro :)

One of these days you should do some tech tips on how you make these videos (If you have already, please post a link so I can check it out). What hardware and programs you use to record and edit? I would like to make similar instructional videos for some of my personal and work documentation.

Good to see these shell tips. Are there cases when the list would be too long for the shell to handle directly requiring something like xargs? (maximum line length) If so, that may be another good tech tip to post. These tech tips are quickly becoming my favorite part of Linux Journal :). They're concise and informative.

pschmitt52's picture

for + seq

On July 7th, 2009 pschmitt52 (not verified) says:

If you want use the for loop as a counting loop
then you could do this:

for x in `seq 1 1000`
do
    echo "line: $x"
done

This will run 1000 iterations.

Anonymous's picture

#!/bin/sh # doing it in C

On July 8th, 2009 Anonymous (not verified) says:

#!/bin/sh

# doing it in C way

for ((I=0;I<=1000;I++))
do
printf "line: %03d\n" $I
done

exsnafu's picture

you can also use the

On July 7th, 2009 exsnafu (not verified) says:

you can also use the following in newer(3+ i think?) versions of bash:

for x in {1..1000}; do
echo "line: $x"
done

Note however that this works:

j=1000
for i in `seq 1 $j`
do
    echo $i
done

Where as this does not:

j=1000
for i in {1..$j}
do
    echo $i
done

To "make" it work do:

j=1000
for i in `eval echo {1..$j}`
do
    echo $i
done
__________________________

Mitch Frazier is an Associate Editor for Linux Journal and the Web Editor for linuxjournal.com.

Post new comment

Please note that comments may not appear immediately, so there is no need to repost your comment.
The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <pre> <ul> <ol> <li> <dl> <dt> <dd> <i> <b>
  • Lines and paragraphs break automatically.

More information about formatting options

Newsletter

Each week Linux Journal editors will tell you what's hot in the world of Linux. You will receive late breaking news, technical tips and tricks, and links to in-depth stories featured on www.linuxjournal.com.
Sign up for our Email Newsletter

Tech Tip Videos

From the Magazine

December 2009, #188

If last month's Infrastrucuture issue was too "big" for you then try on this month's Embedded issue. Find out how to use Player for programming mobile robots, build a humidity controller for your root cellar, find out how to reduce the boot time of your embedded system, and if you're new to embedded systems find out the basics that go into one. You can also read about the Beagle Board, the Mesh Potato and a spate of other interestingly named items. And along with our regular columns don't miss our new monthly column: Economy Size Geek.


Read this issue