6

I have a file that contains data that gets updated over time (mydata). The file looks like this:

1 2 3

With this file, I want to do this (basically handle each number as a separate parameter):

myscript.sh 1 2 3

Since the data is not static but instead updated over time, I want to run this command:

myscript.sh "$(cat mydata)"

But instead I see ./myscript.sh: line 1: 1: command not found

What should I do?

  • 1
    And what does your script contain, since that's an error from within the script? – muru Jan 8 '15 at 16:32
  • sqlite3 /data.db "insert into tbl1 (v1, v2, v3, timeEnter) values($1 $2, $3, DATETIME('NOW'));" – michelemarcon Jan 8 '15 at 16:44
  • Solved! I didn't put the directive #!/bin/bash and was running from sh instead... – michelemarcon Jan 8 '15 at 16:54
  • Still makes me wonder what in it caused 1 to be treated as a command. I don't see process or command substitutions. – muru Jan 8 '15 at 16:56
  • 1
    Split cat's output on IFS. set -f; unset IFS; myscript.sh $(cat mydata) – mikeserv Jan 8 '15 at 17:15
6

"$(cat mydata)" evaluates to a string which contains the content of the file mydata minus any trailing newline. What you want is the list of whitespace-separated words in the file. So, for once, use the command substitution outside of double quotes:

myscript.sh $(cat mydata)

For extra robustness, turn off globbing, so that if a column in mydata contains one of the characters \[*? it isn't interpreted as a file name pattern. You may also want to set IFS to contain the word separator characters, but the default (ASCII whitespace) should be exactly what you need.

(set -f; myscript.sh $(cat mydata))

Alternatively, you could use the read builtin. This reads the first line and ignores the rest (which you could do above by replacing cat by head -n 1).

read -r one two three rest <mydata
myscript.sh "$one" "$two" "$three"
  • 2
    And by the way - there is robust and there is bugged - there is no extra robust. Your recommendation is, in any case, bugged as it does not consider $IFS's current value in either case and relies upon a shell default - (or, it would, if it didn't contradict itself instead) which is a default you have no way of knowing remains still in effect. – mikeserv Jan 9 '15 at 15:03
  • 1
    Note that the default $IFS is only space, tab and newline/linefeed (and NUL with zsh), not the other ASCII whitespace (vertical tab, carriage return, form feed). Some shells take $IFS from the environment which allows system distributors or administrators to set a different default value (though that's rarely done). – Stéphane Chazelas Nov 21 '16 at 12:52
5

That's typically what xargs is for:

xargs myscript.sh < mydata

xargs considers the input as blank or newline separated words where single quote, double quote or backslash is used to escape the separators. xargs will run the command as many times as necessary so as to avoid the limit on the size of arguments (and environment) passed to a command.

3

Instead of passing as multiple arguments, I just pass the arguments as a single array and then do whatever I want with the arguments.

#This is the function which takes a variable length array as an input. 
function function_call() 
{
    all_array_values=$1[@]
    a=("${!all_array_values}")
    for i in "${a[@]}" ; do
        echo "$i"
    done
}


#Here I add all the file contents to the variable named input.  
input=$(cat filename)
#In this step I convert the file contents to an array by splitting on space. 
input_to_array=(${input//' '/ })
#I call the function here. 
function_call input_to_array

Testing

I have the input file as below.

cat filename
1 2 3 4
5
6
7
8

As you can see, I have used multiple lines as well in the input for testing purposes.

Now, when I run the above script, I get the below output.

1
2
3
4
5
6
7
8

I change the input file to have lesser number of arguments and when I run with the lesser arguments, I get the below output.

1
2
3
4

References

https://stackoverflow.com/questions/16461656/bash-how-to-pass-array-as-an-argument-to-a-function https://stackoverflow.com/a/5257398/1742825

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.