2 added 59 characters in body
source | link

You're trying to store a list of strings in a string variable. It doesn't fit. No matter how you access the variable, something is broken.

wget_options='--mirror --no-host-directories' sets the variable wget_options to a string that contains a space. At this point, there is no way to know whether the space is supposed to be part of an option, or a separator between options.

When you access the variable with a quoted substitution wget "$wget_options", the value of the variable is used as a string. This means that it's passed as a single parameter to wget, so it's a single option. This breaks in your case because you intended it to mean multiple options.

When you use an unquoted substitution wget $wget_options, the value of the string variable undergoes an expansion process nicknamed “split+glob”:

  1. Take the value of the variable and split it into whitespace-delimited parts (assuming you have not modified the $IFS variable). This results in an intermediate list of strings.
  2. For each element of the intermediate list, if it is a wildcard pattern that matches one or more files, replace that element by the list of matching files.

This happens to work in your example, because the splitting process turns the space into a separator, but doesn't work in general since an option could contain spaces and wildcard characters.

In ksh, bash, yash and zsh, you can use an array variable. An array in shell terminology is a list of strings, so there is no loss of information. To make an array variable, put parentheses around the array elements when assigning the value to the variable. To access all the elements of the array, use "${VARIABLE[@]}" — this is a generalization of "$@", which forms a list from the elements of the array. Note that you need the double quotes here too, otherwise each element undergoes split+glob.

wget_options=(--mirror --no-host-directories --user-agent="I can haz spaces")
wget "${wget_options[@]}" …

In plain sh, there are no array variables. If you don't mind losing the positional arguments, you can use them to store one list of strings.

set -- --mirror --no-host-directories --user-agent="I can haz spaces"
wget "$@" …

For more information, see Why does my shell script choke on whitespace or other special characters?

You're trying to store a list of strings in a string variable. It doesn't fit. No matter how you access the variable, something is broken.

wget_options='--mirror --no-host-directories' sets the variable wget_options to a string that contains a space. At this point, there is no way to know whether the space is supposed to be part of an option, or a separator between options.

When you access the variable with a quoted substitution wget "$wget_options", the value of the variable is used as a string. This means that it's passed as a single parameter to wget, so it's a single option. This breaks in your case because you intended it to mean multiple options.

When you use an unquoted substitution wget $wget_options, the value of the string variable undergoes an expansion process nicknamed “split+glob”:

  1. Take the value of the variable and split it into whitespace-delimited parts. This results in an intermediate list of strings.
  2. For each element of the intermediate list, if it is a wildcard pattern that matches one or more files, replace that element by the list of matching files.

This happens to work in your example, because the splitting process turns the space into a separator, but doesn't work in general since an option could contain spaces and wildcard characters.

In ksh, bash and zsh, you can use an array variable. An array in shell terminology is a list of strings, so there is no loss of information. To make an array variable, put parentheses around the array elements when assigning the value to the variable. To access all the elements of the array, use "${VARIABLE[@]}" — this is a generalization of "$@", which forms a list from the elements of the array. Note that you need the double quotes here too, otherwise each element undergoes split+glob.

wget_options=(--mirror --no-host-directories --user-agent="I can haz spaces")
wget "${wget_options[@]}" …

In plain sh, there are no array variables. If you don't mind losing the positional arguments, you can use them to store one list of strings.

set -- --mirror --no-host-directories --user-agent="I can haz spaces"
wget "$@" …

For more information, see Why does my shell script choke on whitespace or other special characters?

You're trying to store a list of strings in a string variable. It doesn't fit. No matter how you access the variable, something is broken.

wget_options='--mirror --no-host-directories' sets the variable wget_options to a string that contains a space. At this point, there is no way to know whether the space is supposed to be part of an option, or a separator between options.

When you access the variable with a quoted substitution wget "$wget_options", the value of the variable is used as a string. This means that it's passed as a single parameter to wget, so it's a single option. This breaks in your case because you intended it to mean multiple options.

When you use an unquoted substitution wget $wget_options, the value of the string variable undergoes an expansion process nicknamed “split+glob”:

  1. Take the value of the variable and split it into whitespace-delimited parts (assuming you have not modified the $IFS variable). This results in an intermediate list of strings.
  2. For each element of the intermediate list, if it is a wildcard pattern that matches one or more files, replace that element by the list of matching files.

This happens to work in your example, because the splitting process turns the space into a separator, but doesn't work in general since an option could contain spaces and wildcard characters.

In ksh, bash, yash and zsh, you can use an array variable. An array in shell terminology is a list of strings, so there is no loss of information. To make an array variable, put parentheses around the array elements when assigning the value to the variable. To access all the elements of the array, use "${VARIABLE[@]}" — this is a generalization of "$@", which forms a list from the elements of the array. Note that you need the double quotes here too, otherwise each element undergoes split+glob.

wget_options=(--mirror --no-host-directories --user-agent="I can haz spaces")
wget "${wget_options[@]}" …

In plain sh, there are no array variables. If you don't mind losing the positional arguments, you can use them to store one list of strings.

set -- --mirror --no-host-directories --user-agent="I can haz spaces"
wget "$@" …

For more information, see Why does my shell script choke on whitespace or other special characters?

1
source | link

You're trying to store a list of strings in a string variable. It doesn't fit. No matter how you access the variable, something is broken.

wget_options='--mirror --no-host-directories' sets the variable wget_options to a string that contains a space. At this point, there is no way to know whether the space is supposed to be part of an option, or a separator between options.

When you access the variable with a quoted substitution wget "$wget_options", the value of the variable is used as a string. This means that it's passed as a single parameter to wget, so it's a single option. This breaks in your case because you intended it to mean multiple options.

When you use an unquoted substitution wget $wget_options, the value of the string variable undergoes an expansion process nicknamed “split+glob”:

  1. Take the value of the variable and split it into whitespace-delimited parts. This results in an intermediate list of strings.
  2. For each element of the intermediate list, if it is a wildcard pattern that matches one or more files, replace that element by the list of matching files.

This happens to work in your example, because the splitting process turns the space into a separator, but doesn't work in general since an option could contain spaces and wildcard characters.

In ksh, bash and zsh, you can use an array variable. An array in shell terminology is a list of strings, so there is no loss of information. To make an array variable, put parentheses around the array elements when assigning the value to the variable. To access all the elements of the array, use "${VARIABLE[@]}" — this is a generalization of "$@", which forms a list from the elements of the array. Note that you need the double quotes here too, otherwise each element undergoes split+glob.

wget_options=(--mirror --no-host-directories --user-agent="I can haz spaces")
wget "${wget_options[@]}" …

In plain sh, there are no array variables. If you don't mind losing the positional arguments, you can use them to store one list of strings.

set -- --mirror --no-host-directories --user-agent="I can haz spaces"
wget "$@" …

For more information, see Why does my shell script choke on whitespace or other special characters?