Why are solely *some* (boolean and string) values quoted in Fedora's default GRUB2 configuration?

My current GRUB2 configuration is undermentioned:

GRUB_TIMEOUT=15 # Original: GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="gfxterm" # Original: GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="" # Original: GRUB_CMDLINE_LINUX="rhgb quiet"
GRUB_DISABLE_RECOVERY="false" # Original: GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
GRUB_GFXMODE=2560x1440,auto
GRUB_DISABLE_OS_PROBER=false

If I were to convert it to the undermentioned (or another consistent variation thereof) would it be exactly equivalent?

GRUB_TIMEOUT=15 # Original: GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT="saved"
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="gfxterm" # Original: GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="" # Original: GRUB_CMDLINE_LINUX="rhgb quiet"
GRUB_DISABLE_RECOVERY=false # Original: GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG=true
GRUB_GFXMODE="2560x1440,auto"
GRUB_DISABLE_OS_PROBER=false

If so, why are solely some values quoted by default? If not, why do solely some necessitate quotation?

If you’re struggling to see which are different, some examples are 2560x1440,auto becoming "2560x1440,auto", and GRUB_DISABLE_RECOVERY="false" becoming GRUB_DISABLE_RECOVERY=false.

bugs.launchpad.net/ubuntu/+source/grub2/+bug/568649/comments/2 appears to state that they’re mostly equivalent:

I can tell you for absolute fact that it makes no difference whether a single word like true is quoted or unquoted in the shell. (If we were talking about something containing multiple words or special characters then that would be different, but that doesn’t seem to apply here.)

However, situations like the CSVs of GRUB_GFXMODE are ambiguous (as are the boolean and integral values).

I think those variable assignments are parsed by Bash scripts. (Check /etc/grub.d to be sure. I would, but I don’t have Grub installed on my PC.) Since Bash doesn’t have booleans, the right-hand values will be treated as strings either way (quoted or unquoted). It would matter for something like JSON that does support boolean values. For JSON, unquoted whatever: true would not be the same as quoted whatever: "true". To demonstrate:

$ node -e 'TEST={ whatever: true }; if (TEST.whatever === true) { console.log("It is true!"); };'
It is true!
$ node -e 'TEST={ whatever: "true" }; if (TEST.whatever === true) { console.log("It is true!"); };'
$

But in Bash:

$ bash -c 'TEST=true; if [[ $TEST == true ]]; then echo "It is true!"; fi'
It is true!
$ bash -c 'TEST="true"; if [[ $TEST == true ]]; then echo "It is true!"; fi'
It is true!
$

Of course, you must quote the right-hand side in Bash if there are spaces.

$ TEST=
$ TEST=one two
bash: two: command not found
$ echo $TEST

$ TEST="one two"
$ echo $TEST
one two
$

Note that [[ ]] counts as a quoted context but [ ] does not.

$ echo $TEST
one two
$ [[ -n $TEST ]] && echo it worked!
it worked!
$ [ -n $TEST ] && echo it worked!
bash: [: one: binary operator expected
3 Likes

@glb, many thanks for those tests. That confirms it for booleans.

Additionally, stackoverflow.com/questions/72649342/are-integers-in-bash-signed-by-default/72649508#comment128332004_72649342 states that:

bash doesn’t really have “integers”. When you store a number in a variable, it’s a string (that happens to be a sequence of digits). When you do math in bash, it parses those strings into integers (of a platform-dependent type), does the math, then converts the result back to a string of digits for storage.

Summarily, integers appear to be strings too.

To my knowledge, /etc/default/grub is a POSIX-compliant shell script (albeit without the shebang) so that should mean that every value should be quoted.

This is probably an example of the file being lazily written by whoever decided these defaults for Fedora.

To demonstrate, the undermentioned functions identically to my aforementioned example:

GRUB_TIMEOUT="15" # Original: GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT="saved"
GRUB_DISABLE_SUBMENU="true"
GRUB_TERMINAL_OUTPUT="gfxterm" # Original: GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="" # Original: GRUB_CMDLINE_LINUX="rhgb quiet"
GRUB_DISABLE_RECOVERY="false" # Original: GRUB_DISABLE_RECOVERY="true"
GRUB_ENABLE_BLSCFG="true"
GRUB_GFXMODE="2560x1440,auto"
GRUB_DISABLE_OS_PROBER="false"

2 Likes