1

So, I want to create a script where I check sth from a website. I have a text file with different websites in it and I want to check all websites simultaneously. To do this I'm creating a command step by step in a variable calling a function which will check every website. This is my code:

checkWebsite(){
    WEBSITE="$2"
    echo "Parameter is $WEBSITE"
}

COUNTER=0;

input=websites.txt

myCommand=()
while IFS= read -r line
do
    if [[ "$line" != "#"* ]]; #ignoring comments if there are any
    then
        myCommand[COUNTER]="checkWebsite $line"
        COUNTER=$((COUNTER + 1))
        myCommand[COUNTER]=" & "
        COUNTER=$((COUNTER + 1))
    fi
done < "$input"

unset 'myCommand[${#myCommand[@]}-1]' #deleting the last " & "

echo "MY COMMAND: "
echo ${myCommand[@]}
echo " "

echo ${myCommand[0]}
checkWebsite ${myCommand[0]}
"${myCommand[0]}"

These are the results: results

As you can see, if I call the function from the script everything is ok but if I call the function from the variable it doesn't work. I understand why this is happening(it's like I run that command from the terminal) but I don't know how can I make it run the function from the script when I execute the command from the variable. Does anyone know how can I make that happen?

Thanks in advance

4
  • Putting it in a variable makes it harder and messier than it has to be. Is there a reason why you're not just running it directly? Commented Nov 24, 2018 at 20:08
  • Asked and answered a lot of times: bash command parameter substitution site:stackoverflow.com. Which would you like as your duplicate? Commented Nov 24, 2018 at 20:17
  • Also see BashFAQ #50. "${myCommand[0]}" entirely defeats the whole purpose of using an array -- dereffing just the first element means it's just another string. Commented Nov 24, 2018 at 20:19
  • BTW, declare -p myCommand gives you a much more accurate idea of your array's contents than echo ${myCommand[@]} does. (For that matter, printf '%q\n' "${myCommand[@]}" would be an improvement as well). Commented Nov 25, 2018 at 0:39

1 Answer 1

3

Don't use an array here. It causes a lot of trouble and adds no value whatsoever. Instead, start your background tasks inside the loop:

while IFS= read -r line; do
  [[ "$line" = "#"* ]] || checkWebsite "$line" &
done < "$input"

If you really want an array, populate it from the loop, and -- again -- start items individually without it.

websites=( )
while IFS= read -r line; do
  [[ "$line" = "#"* ]] || websites+=( "$line" )
done < "$input"

for site in "${websites[@]}"; do
  checkWebsite "$site" &
done

Why doesn't the other approach work? Because & only acts as a command separator when parsed as syntax, and parameter expansion results are data, not syntax.

You would need to use eval to make your expansion results parse as syntax; unless done with great care, this would cause serious security vulnerabilities.

Sign up to request clarification or add additional context in comments.

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.