LinuxQuestions.org
Help answer threads with 0 replies.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices

Reply
 
Search this Thread
Old 09-04-2007, 11:32 AM   #1
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949
bash syntax: looping through a comma-separated list


How can I get bash to read a list of inputs one at a time?

I'm trying to process some video and I would like to run the same command at predetermined intervals on the file. I'd like to use a comma-delineated list of timestamps as the input. I want to do something like this:

for TIME in "time1,time2,time3,time4" ; do command @ $TIME ; done

But I can't figure out how to get bash to process such a list. I tried looking at the 'read' command, but I even figure out exactly what it's supposed to do, or whether it would apply in this case. I've found a way to input the times via a text file (using the 'line' command), but it's a big hassle since I have to edit the list so that there's one entry per line. There must be a way to use the list as-is. I've searched this forum and this web but haven't found anything useful.

I want to be able to do this both from the command prompt and eventually through an actual script. Can someone help me out here?


PS: As a related question, is there any easy way to generate a list of regularly spaced timestamps, say every 300 seconds, with the format "hh:mm:ss"?
 
Old 09-04-2007, 11:51 AM   #2
nx5000
Senior Member
 
Registered: Sep 2005
Location: Out
Posts: 3,307

Rep: Reputation: 52
Something like that?

1)
IFS=","
var="a,b,c"

for v in $var
do echo "$v"
done

2)

while /bin/true; do sleep 300; date +"%H:%M:%S"; done
 
Old 09-04-2007, 11:56 AM   #3
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,508

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Quote:
Originally Posted by David the H. View Post
I've found a way to input the times via a text file (using the 'line' command), but it's a big hassle since I have to edit the list so that there's one entry per line.
This can be done as in
Code:
> echo a,b,c,d | sed s/,/\\n/g
a
b
c
d
 
Old 09-04-2007, 12:35 PM   #4
unSpawn
Moderator
 
Registered: May 2001
Posts: 27,462
Blog Entries: 54

Rep: Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899
...and with a default IFS "for v in ${var//,/ }"?
 
Old 09-04-2007, 12:45 PM   #5
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Original Poster
Rep: Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949
Quote:
Originally Posted by nx5000 View Post
Something like that?

1)
IFS=","
var="a,b,c"

for v in $var
do echo "$v"
done
Ok, this seems to work. I had to look up what IFS is. Interesting. But it still seems a bit sloppy though. Wouldn't I have to manually unset the ISF variable after I finished with it, or risk having it interfere with other shell uses? Is there no way to feed the list in directly, without having to resort to a variable or file?
Quote:
2)

while /bin/true; do sleep 300; date +"%H:%M:%S"; done
This doesn't seem to do what I want. This generates a list of real-time timestamps. I just want to create a count of 5 minute intervals from 00:00:00 up to, say 01:30:00 (for example).

@colucix: Thank you. That does make converting the list between formats easier. But I'd still like to avoid having to use a text file altogether.
 
Old 09-04-2007, 12:51 PM   #6
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Original Poster
Rep: Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949
unSpawn, I just tried your string, but that doesn't seem to work. It only removes the commas, concatenating all the values together into a single long one.
 
Old 09-04-2007, 02:17 PM   #7
colucix
Moderator
 
Registered: Sep 2003
Location: Bologna
Distribution: CentOS 6.5 OpenSuSE 12.3
Posts: 10,508

Rep: Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957Reputation: 1957
Quote:
Originally Posted by David the H. View Post
I just want to create a count of 5 minute intervals from 00:00:00 up to, say 01:30:00 (for example).
To generate a list of times, I'd suggest to use a while loop, and increase time accordingly to the choosen timestep, like this:
Code:
#/bin/bash
# --------------------------------------------------
#  Initialize counter
# --------------------------------------------------
min=0

# --------------------------------------------------
#  Loop from 0 to 90 every 5 minutes
# --------------------------------------------------
while [ $min -le 90 ] ; do

    time=`date -d "00:00:00 $min minutes" +%H:%M:%S`
    
    echo $time
    
    min=$((min + 5))

done
The date command in linux is very flexible and let to output any date (not only "now") absolute or relative. See info date for details. Cheers!

Last edited by colucix; 09-04-2007 at 02:21 PM.
 
Old 09-04-2007, 06:32 PM   #8
rch1231
Member
 
Registered: Mar 2007
Location: Bedford, Texas
Posts: 31

Rep: Reputation: 15
Based on your original question here are a couple of ideas:

The shell for command looks for white space between entries and you could use this for example:

for x in time1 time2 time3 do ; <script> ; done

or you can put the entries in a file and have linux execute a shell command to read the file. For example if you have a list of the times in a file called dotimes and you want the for statement to read the list you could use the back quote (just to the left of the 1 key).

for x in `cat dotimes` do ; <script> ; done

as a bash script you could call it would look like this:

#!/bin/bash
for x in `cat /home/me/dotimes`
do
<script>
done

But the simplest way I can think of to do something like what you want is to run a simple loop with the sleep command. Say you want to list the contents of the /var/tmp directory every 5 minutes to see if the file is growing. From the command line you would type the following:

while true
do
date
/bin/ls -la /var/tmp
sleep 300
done

The command would run every 5 minutes till you stop (break AKA <CTRL> C) it. It would list the date at the beginning of each run so you could see the time change.

Hope this helps.
rhoward1231@yahoo.com
 
Old 09-05-2007, 04:50 AM   #9
nx5000
Senior Member
 
Registered: Sep 2005
Location: Out
Posts: 3,307

Rep: Reputation: 52
Quote:
Wouldn't I have to manually unset the ISF variable after I finished with it, or risk having it interfere with other shell uses?
If you put the code I posted _in a script_ (and not directly in your current shell) then as a normal script, bash will create a new subshell, execute the script and then return to the parent shell. Then nothing is kept.
If you do it from the command line then yes, you have to set it back,maybe like this:
old_IFS=${IFS}
blabah
IFS=${old_IFS}

Well, it's not that tricky I think. Otherwise unSpawn method is shorter but you need to be using bash, it's not POSIX compliant.

Code:
$ echo $0
/bin/bash

$ var="a,b,c" ; for v in ${var//,/ }; do echo $v; done
a
b
c

$ /bin/sh

$ echo $0
/bin/sh

$var="a,b,c" ; for v in ${var//,/ }; do echo $v; done
/bin/sh: Syntax error: Bad substitution
 
Old 09-05-2007, 11:50 AM   #10
unSpawn
Moderator
 
Registered: May 2001
Posts: 27,462
Blog Entries: 54

Rep: Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899Reputation: 2899
Quote:
Originally Posted by David the H. View Post
unSpawn, I just tried your string, but that doesn't seem to work. It only removes the commas, concatenating all the values together into a single long one.
Hmm, maybe you didn't add the space after the slash or you're not using Bash?
 
Old 09-06-2007, 10:23 AM   #11
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Original Poster
Rep: Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949
Thanks for the advice everyone. Sorry I couldn't get back to you for a couple of days. There's a lot I have to reply to.

colucix: Now that appears to do just what I was looking for. A bit of modification to add some user inputs and that script will be perfect for generating various lists of timestamps.

rch1231: A-ha, I see. So it's the comma separation that's doing it. The reason I've been using commas is because that's how all the dvd authoring programs handle their chapter lists, and I've just been copy/pasting the numbers. But now I can generate my own lists or use the IFS setting or unSpawn's method to work around it. Speaking of which...

unSpawn: You were right, I did miss the space. It's always the little typos that get you, isn't it? It works when I type it in correctly. I'll probably go with that, since I don't have to worry about setting external variables that way.

nx5000: That's what I thought. I want to be able to do this both with a script and quick-&-dirty manually, so I want to be careful about the IFS setting when I'm doing the latter. And no worries about compatibility. I'll only be using bash.

I appreciate all the help. Now to implement what I've learned.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Looping a bash script SoulGrind Linux - Newbie 5 09-22-2006 06:03 PM
Looping thru a list in a file BruceC Linux - Newbie 12 05-19-2004 08:51 AM
Reading comma-separated data from file MeLassen Programming 4 04-04-2004 02:41 PM
Bash case structure (looping) ravvar Programming 4 10-07-2003 07:07 PM
address match list syntax for bind dguy Linux - Networking 2 07-16-2002 09:08 AM


All times are GMT -5. The time now is 11:37 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration