0

I have a bash script which asks for two arguments with a space between them. Now I would like to automate filling out the prompt in the command line with reading from a text file. The text file contains a list with the argument combinations.

So something like this in the command line I think;

for line in 'cat text.file' ; do script.sh ; done

Can this be done? What am I missing/doing wrong?

Thanks for the help.

1

4 Answers 4

4

A while loop is probably what you need. Put the space separated strings in the file text.file :

cat text.file
bingo yankee
bravo delta

Then write the script in question like below.

#!/bin/bash
while read -r arg1 arg2
do
 /path/to/your/script.sh "$arg1" "$arg2"
done<text.file
Sign up to request clarification or add additional context in comments.

1 Comment

This should be the accepted answer. I reference to this answer in my own.
1

Don't use for to read files line by line

Try something like this:

#!/bin/bash
ARGS= 
while IFS= read -r line; do
    ARGS="${ARGS} ${line}"
done < ./text.file

script.sh "$ARGS"

This would add each line to a variable which then is used as the arguments of your script.

1 Comment

mywiki doesn't seem to know about safe practices of using for loops by utilizing double quotes to preserve literal strings and file names with spaces/special characters. Even if it isn't the most efficient practice, it can still be done while avoiding the errors mentioned in the wiki. A while loop is the best route to take here though so I agree with your answer solution.
1

'cat text.file' is a string literal, $(cat text.file) would expand to output of command however cat is useless because bash can read file using redirection, also with quotes it will be treated as a single argument and without it will split at space tab and newlines.

Bash syntax to read a file line by line, but will be slow for big files

while IFS= read -r line; do ... "$line"; done < text.file
  • unsetting IFS for read command preserves leading spaces
  • -r option preserves \

another way, to read whole file is content=$(<file), note the < inside the command substitution. so a creative way to read a file to array, each element a non-empty line:

read_to_array () {
    local oldsetf=${-//[^f]} oldifs=$IFS
    set -f
    IFS=$'\n' array_content=($(<"$1")) IFS=$oldifs
    [[ $oldsetf ]]||set +f
}

read_to_array "file"
for element in "${array_content[@]}"; do ...; done
  • oldsetf used to store current set -f or set +f setting
  • oldifs used to store current IFS
  • IFS=$'\n' to split on newlines (multiple newlines will be treated as one)
  • set -f avoid glob expansion for example in case line contains single *
  • note () around $() to store the result of splitting to an array

2 Comments

Just as a suggestion, you might look into breaking the larger blob of code into a more readable format (perhaps shell script format) since it seems apparent that the OP is new to shell code and best practices. This will make it a bit easier for him/her to read your solution. Also note that $(<file) will load the entire file into memory. This is fine for smaller files but not so much for larger files.
@Yokai thank you for your feedback i've changed to a function also to be easier to use
0

If I were to create a solution determined by the literal of what you ask for (using a for loop and parsing lines from a file) I would use iterations determined by the number of lines in the file (if it isn't too large).

Assuming each line has two strings separated by a single space (to be used as positional parameters in your script:

file="$1"
f_count="$(wc -l < $file)"
for line in $(seq 1 $f_count)
do

    script.sh $(head -n $line $file | tail -n1) && wait

done

You may have a much better time using sjsam's solution however.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.