How to pass the content of a file as multiple arguments in bash
Solution 1
"$(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"
Solution 2
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.
Solution 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
michelemarcon
Hello, I'm a Java software engineer. I also have some Android and Linux experience.
Updated on September 18, 2022Comments
-
michelemarcon almost 2 years
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?
-
muru over 9 yearsAnd what does your script contain, since that's an error from within the script?
-
michelemarcon over 9 yearssqlite3 /data.db "insert into tbl1 (v1, v2, v3, timeEnter) values($1 $2, $3, DATETIME('NOW'));"
-
michelemarcon over 9 yearsSolved! I didn't put the directive #!/bin/bash and was running from sh instead...
-
muru over 9 yearsStill makes me wonder what in it caused
1
to be treated as a command. I don't see process or command substitutions. -
mikeserv over 9 yearsSplit cat's output on IFS.
set -f; unset IFS; myscript.sh $(cat mydata)
-
-
mikeserv over 9 yearsAnd 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. -
Stéphane Chazelas over 7 yearsNote 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). -
Shicheng Guo about 3 yearsHow to handle it if mydata have multiple rows? current command only take the 1st row.
-
Stéphane Chazelas about 3 years@ShichengGuo, what do you mean by row? If you mean line, then as I said newline is one of the characters
xargs
treats as delimiter, so ifmydata
containsfoo bar\nbaz\n
, your command will be passedfoo
,bar
andbaz
as arguments.