2

I would like to iterate through a file containing dates (named dates.txt) in the following format:

2009 08 03 08 09
2009 08 03 09 10
2009 08 03 10 11
2009 08 03 11 12
2009 08 03 12 13
2009 08 03 13 14

And pass each field of each line as a positional parameter to another script.

ie: the other script is executed by putting the following at the command line:

$ . the_script 2009 08 03 08 09

I have tried for i in $(./dates.txt);do echo ${i};done

but get:

./dates: line 1: 2009: command not found
./dates: line 2: 2009: command not found
./dates: line 3: 2009: command not found
./dates: line 4: 2009: command not found
./dates: line 5: 2009: command not found
./dates: line 6: 2009: command not found

from this i can tell it is working through each line but perhaps getting hung up on each field?

Because of the above, I have yet been able to figure out how to pass the read lines as positional parameters to the other script. Not sure where to work it in either? Help, please!

  • 1
    Why are you using . the_script to run your script? This is called sourcing and should only be done when you explicitly want to make changes to the shell context, eg, change the current working directory, or to set functions or variables. Otherwise it "pollutes" your shell with any variables or functions that you define in the script, as well as (potentially) changing the current working directory. And if you call exit in a sourced script you'll exit the shell. – PM 2Ring Jan 5 '15 at 9:38
  • noted. it was more of a quick use. Please post solutions too and not merely problems. I am here to learn. i.e.: what SHOULD i use instead? – geokrowding Jan 5 '15 at 9:43
  • 1
    You should give the_script execute permissions and a shebang line so you can just run it directly. You can set file permissions in your GUI file manager, or you can do it on the commandline using the chmod command. – PM 2Ring Jan 5 '15 at 9:52
  • Note that I didn't say it is wrong to source your script, just that it may cause undesirable side-effects. You may have had very good reasons for sourcing it, but it was impossible to tell from the info in your question. – PM 2Ring Jan 5 '15 at 9:54
  • 1
    fair enough, thanks for the tips. Consider the file "shebanged" and it has been properly given permissions to execute (chmod +x). – geokrowding Jan 5 '15 at 9:58
4

Perhaps you mean something like this?

while read -d $'\n' i; do echo $i;done <./dates

while read -d $'\n' i; do . the_script $i;done <./dates
  • FWIW, -d $'\n' isn't strictly necessary, as \n is the default delimiter of read. – PM 2Ring Jan 5 '15 at 9:29
  • The less than symbol < is used to input a file as an argument. This works great while read i; do ./the_script $i;done <./lstplanets. What is the . for? I didn't use it and it works fine. – iyrin Jan 5 '15 at 10:02
  • @RyanLoremIpsum: My 1st comment on the question describes what the . does. – PM 2Ring Jan 5 '15 at 10:04
  • this worked great, thanks! while read i; do ./avg_hr.sh $i; done <./dates – geokrowding Jan 5 '15 at 10:28
  • 1
    Similarly, always specifying -r when using read is a Good Idea, even when it's unnecessary because you know the data won't contain backslashes (like in this case). Because if you leave it out when you do need it, then Bad Things happen. So it's a good habit to always use -r so that you never forget about it. :) – PM 2Ring Jan 5 '15 at 12:11
2

If sourcing (.) isn't needed, this sounds like a job for xargs:

xargs -a dates.txt -rL1 the_script
  • xargs reads a line of input and then uses it for arguments for the command specified. The default line delimiter is the newline.
  • We can pipe data to it from other commands, or specify an input file using -a.
  • Since exactly one line is to be used per invocation of script, we specify the -r (don't run if line is empty) and -L (use at most N lines per invocation) options.
0

Use cat in your command and make sure you use the correct path to file name if the scripts are not in the same directory. If the list is dates.txt then use $(cat ./dates.txt). Edited typo here. Include the .txt

Here is an example:

A list of dates named dates.txt.

2009 08 03 08 09
2009 08 03 09 10
2009 08 03 10 11
2009 08 03 11 12
2009 08 03 12 13
2009 08 03 13 14

A script named lstdates.sh to echo the planets in that list. Edited This runs in a sub shell to that the internal field separator (IFS)1 is not changed outside of the subshell2.

#!/bin/bash
# Listing each date as an argument for `the_script`.

# Parenthesis runs in a subshell    
( 
  # IFS line break
  IFS=$'\012'
  for dates in $(cat ./dates.txt)
  do
    echo $(./the_script $dates)
  done
)

By default, IFS recognizes each whitespace as the end of a field. IFS=$'\012' recognizes each new line as the end of a field. If each line is wrapped in double quotes such as "2009 08 03 08 09", then the default IFS will work.

the_script only contains the following.

#!/bin/bash
echo $1

Reference: Advanced Bash-Scripting Guide Chapter 11. Loops and Branches

  • 2
    This doesn't do what geokrowding wants. If you try your code using the data in the OP you'll see that it prints each number from the file on a separate line. In other words, each invocation of echo gets passed a single word of the file. BTW, $(cat planets) is preferred over the form using backticks, see mywiki.wooledge.org/BashFAQ/082 . Another reason not to use backticks is that it's not easy to display backticks in these comments. :) – PM 2Ring Jan 5 '15 at 9:26
  • Hey thanks, PM 2Ring. It now passes each line as and argument to the script called. Although, Miroslav's solution is way easier imo. – iyrin Jan 5 '15 at 10:05
  • Are you sure? Try it on the OP data, and you'll see it still doesn't work right. Also, echo $(some_command) is weird. – PM 2Ring Jan 5 '15 at 10:12
  • Ah good eye. Updated and explanation added. It is only working if I keep the echo command. To test, I am passing it to the_script which only contains echo $1. This does seem weird and redundant tho. – iyrin Jan 5 '15 at 10:58
  • This is pretty well explained here, although there are no examples for passing the output of each line as an argument for a script. stackoverflow.com/questions/10748703/… – iyrin Jan 5 '15 at 11:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.