<div>Here is an updated patch with the following improvements:  <br></div><div><br></div><div>* Preserves an "advanced options" description, such as "(recovery mode)", in <br></div><div>the submenu entries.  <br></div><div><br></div><div>* Suppresses options in the submenu that are equivalent to an option in the<br></div><div>main menu.  <br></div><div><br></div><div>* Main-menu entries that open submenus are now indented, so the main menu is<br></div><div>more readable.  (This affects only submenus generated by the os-prober script,<br></div><div>not by other GRUB scripts.)  <br></div><div><br></div><div>* In part of the script, I made the indentation more consistent (in the script<br></div><div>only, not in its output) so the logic flow is more understandable.  <br></div><div><br></div><div>The following was generated with "diff -ud" using diff version 3.3.  <br></div><div><br></div><div>--- 30_os-prober        2016-07-22 20:09:25.000000000 -0400<br></div><div>+++ 15_os-prober    2017-03-03 17:43:52.371188836 -0500<br></div><div>@@ -27,6 +27,35 @@<br></div><div><br></div><div>. "${datarootdir}/grub/grub-mkconfig_lib"<br></div><div><br></div><div>+safe_echo () { printf %s\\n "$*" ; }<br></div><div>+safe_echo_n () { printf %s "$*" ; }<br></div><div>+# Based on <a href="http://www.etalabs.net/sh_tricks.html">http://www.etalabs.net/sh_tricks.html</a><br></div><div>+<br></div><div>+rtrim() {  # remove trailing whitespace characters<br></div><div>+  local var="$*"<br></div><div>+  var="${var%"${var##*[![:space:]]}"}"<br></div><div>+  safe_echo_n "$var"<br></div><div>+}<br></div><div>+# Based on <a href="http://stackoverflow.com/a/3352015">http://stackoverflow.com/a/3352015</a><br></div><div>+<br></div><div>+name_to_compare () { echo "${1}" | tr -c "[:alpha:]" " " | tr -s " " | \<br></div><div>+                     tr "[:upper:]" "[:lower:]" | \<br></div><div>+                     sed "s/[ ]\+$//" ; }<br></div><div>+# This function is used in detecting whether an /etc/lsb-release file's<br></div><div>+# DISTRIB_CODENAME is redundantly included at the end of the file's<br></div><div>+# DISTRIB_DESCRIPTION. <br></div><div>+#   Convert all non-letters in ${1} to spaces. <br></div><div>+#   Then convert multiple consecutive spaces to single spaces. <br></div><div>+#   Then convert all uppercase letters to lowercase. <br></div><div>+#   Then remove trailing spaces if present (sed "s/ $//" doesn't seem to work<br></div><div>+# for this). <br></div><div>+#   We do these things so an LCODENAME of "betsy" will be detected at the end<br></div><div>+# of an LDESC of "LMDE 2 (Betsy)", but not in an LDESC of "LMDE blah b_e.t-s.y"<br></div><div>+       <br></div><div>+menu_entry_values () { echo ${1} | cut -d ':' --complement -f 3 ; }<br></div><div>+# Get the values (other than the displayed name) of a menu entry. <br></div><div>+# This shell function is used to detect whether 2 menu entries are the same. <br></div><div>+<br></div><div>found_other_os=<br></div><div><br></div><div>adjust_timeout () {<br></div><div>@@ -244,71 +273,145 @@<br></div><div>           LLABEL="${LONGNAME}"<br></div><div>         fi<br></div><div><br></div><div>-    if [ "${LROOT}" != "${LBOOT}" ]; then<br></div><div>-       LKERNEL="${LKERNEL#/boot}"<br></div><div>-     LINITRD="${LINITRD#/boot}"<br></div><div>-   fi<br></div><div>+        if [ "${LROOT}" != "${LBOOT}" ]; then<br></div><div>+          LKERNEL="${LKERNEL#/boot}"<br></div><div>+          LINITRD="${LINITRD#/boot}"<br></div><div>+        fi<br></div><div><br></div><div>-    if [ -z "${prepare_boot_cache}" ]; then<br></div><div>-       prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | grub_add_tab)"<br></div><div>-          [ "${prepare_boot_cache}" ] || continue<br></div><div>-      fi<br></div><div>+        if [ -z "${prepare_boot_cache}" ]; then<br></div><div>+          prepare_boot_cache="$(prepare_grub_to_access_device ${LBOOT} | grub_add_tab)"<br></div><div>+          [ "${prepare_boot_cache}" ] || continue<br></div><div>+        fi<br></div><div><br></div><div>-    found_other_os=1<br></div><div>-      onstr="$(gettext_printf "(on %s)" "${DEVICE}")"<br></div><div>- recovery_params="$(echo "${LPARAMS}" | grep 'single\|recovery')" || true<br></div><div>-  counter=1<br></div><div>-     while echo "$used_osprober_linux_ids" | grep 'osprober-gnulinux-$LKERNEL-${recovery_params}-$counter-$boot_device_id' > /dev/null; do<br></div><div>-        counter=$((counter+1));<br></div><div>-    done<br></div><div>-  if [ -z "$boot_device_id" ]; then<br></div><div>-       boot_device_id="$(grub_get_device_id "${DEVICE}")"<br></div><div>-     fi<br></div><div>-    used_osprober_linux_ids="$used_osprober_linux_ids 'osprober-gnulinux-$LKERNEL-${recovery_params}-$counter-$boot_device_id'"<br></div><div>+        LSB_QUERY_MOUNT_POINT=$(findmnt -flno TARGET ${DEVICE})<br></div><div>+       <br></div><div>+        if [ -z "${LSB_QUERY_MOUNT_POINT}" ] ; then<br></div><div>+          LSB_QUERY_MOUNT_POINT=$(mktemp -d)<br></div><div>+          mount ${DEVICE} ${LSB_QUERY_MOUNT_POINT}<br></div><div>+          TEMP_MOUNT="true"<br></div><div>+          # It appears that this code doesn't run:  Although syslog indicates<br></div><div>+          # that /usr/lib/os-probes/mounted/40lsb indeed scans unmounted<br></div><div>+          # partitions, it seems that /usr/bin/os-prober (which is indirectly<br></div><div>+          # the parent process of "40lsb") still doesn't report any OS that<br></div><div>+          # exists on such a partition.  The partition tested was formatted as<br></div><div>+          # btrfs. <br></div><div>+        else<br></div><div>+          TEMP_MOUNT="false"<br></div><div>+        fi<br></div><div>+       <br></div><div>+        LSB_DATABASE=${LSB_QUERY_MOUNT_POINT}/etc/lsb-release<br></div><div>+       <br></div><div>+        LCODENAME=$(grep ^DISTRIB_CODENAME ${LSB_DATABASE} | cut -d "=" -f 2)<br></div><div>+        LDESC=$(grep ^DISTRIB_DESCRIPTION ${LSB_DATABASE} | cut -d "=" -f 2)<br></div><div>+       <br></div><div>+        if [ "x${TEMP_MOUNT}" = xtrue ] ; then<br></div><div>+          umount ${LSB_QUERY_MOUNT_POINT}<br></div><div>+        fi<br></div><div>+       <br></div><div>+        if safe_echo "${LDESC}" | grep -E "^(['\"]).*\1$" >/dev/null; then<br></div><div>+          LDESC=$(safe_echo "${LDESC}" | cut -c 2- | rev | cut -c 2- | rev)<br></div><div>+        fi  # If ${LDESC} is quoted, then remove the quote marks. <br></div><div>+       <br></div><div>+        LSPECIAL_MODE=$(rtrim "$(safe_echo "$LLABEL" | \<br></div><div>+                                 grep -Eo "\([^(]*\)[[:space:]]*$")")<br></div><div>+        # Get any parenthesized string (optionally followed by whitespace) at the end<br></div><div>+        # of $LLABEL. <br></div><div>+       <br></div><div>+        if [ -n "${LSPECIAL_MODE}" ]; then<br></div><div>+          LSPECIAL_MODE=" ${LSPECIAL_MODE}"<br></div><div>+        fi<br></div><div>+        # After this "if", $LSPECIAL_MODE either is null or starts with " (" <br></div><div>+       <br></div><div>+        LKERNEL_DISPLAY=$(safe_echo "${LKERNEL}" | cut -d "-" -f 2-)<br></div><div>+        # Try to extract the version number of the kernel image file. <br></div><div>+       <br></div><div>+        LDESC_CMP=$(name_to_compare "${LDESC}")<br></div><div>+        LCODENAME_CMP=$(name_to_compare "${LCODENAME}")<br></div><div>+       <br></div><div>+        if safe_echo "${LDESC_CMP}" | grep -E "${LCODENAME_CMP}$" >/dev/null; then<br></div><div>+          # ${LDESC} ends in ${LCODENAME}. <br></div><div>+          OS_SUBMENU="${LDESC}"<br></div><div>+        else<br></div><div>+          # ${LDESC} doesn't end in ${LCODENAME}. <br></div><div>+          OS_SUBMENU="${LDESC} \"${LCODENAME}\""<br></div><div>+        fi<br></div><div>+       <br></div><div>+        OS="${OS_SUBMENU}${LSPECIAL_MODE}, with Linux kernel ${LKERNEL_DISPLAY}"<br></div><div>+        # Examples: <br></div><div>+        # Ubuntu 13.04 "raring", with Linux kernel 3.8.0-35-generic<br></div><div>+        # LMDE 2 Betsy, with Linux kernel 3.16.0-4-amd64<br></div><div>+        #   (if codename is "betsy" & description ends in "Betsy")<br></div><div>+       <br></div><div>+        found_other_os=1<br></div><div>+             onstr="$(gettext_printf "(on %s)" "${DEVICE}")"<br></div><div>+        recovery_params="$(echo "${LPARAMS}" | grep 'single\|recovery')" || true<br></div><div>+         counter=1<br></div><div>+            while echo "$used_osprober_linux_ids" | grep 'osprober-gnulinux-$LKERNEL-${recovery_params}-$counter-$boot_device_id' > /dev/null; do<br></div><div>+             counter=$((counter+1));<br></div><div>+       done<br></div><div>+         if [ -z "$boot_device_id" ]; then<br></div><div>+            boot_device_id="$(grub_get_device_id "${DEVICE}")"<br></div><div>+        fi<br></div><div>+           used_osprober_linux_ids="$used_osprober_linux_ids 'osprober-gnulinux-$LKERNEL-${recovery_params}-$counter-$boot_device_id'"<br></div><div><br></div><div>-        if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then<br></div><div>-            cat << EOF<br></div><div>+        if [ "x$is_top_level" = xtrue ] && [ "x${GRUB_DISABLE_SUBMENU}" != xy ]; then<br></div><div>+          printf "Adding '%s' to menu\n" "${OS}" >&2<br></div><div>+          cat << EOF<br></div><div>menuentry '$(echo "$OS $onstr" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-simple-$boot_device_id' {<br></div><div>EOF<br></div><div>-       save_default_entry | grub_add_tab<br></div><div>-      printf '%s\n' "${prepare_boot_cache}"<br></div><div>-        cat <<  EOF<br></div><div>+          save_default_entry | grub_add_tab<br></div><div>+               printf '%s\n' "${prepare_boot_cache}"<br></div><div>+         cat <<  EOF<br></div><div>linux ${LKERNEL} ${LPARAMS}<br></div><div>EOF<br></div><div>-            if [ -n "${LINITRD}" ] ; then<br></div><div>-          cat << EOF<br></div><div>+          if [ -n "${LINITRD}" ] ; then<br></div><div>+            cat << EOF<br></div><div>initrd ${LINITRD}<br></div><div>EOF<br></div><div>-            fi<br></div><div>-        cat << EOF<br></div><div>+          fi<br></div><div>+          cat << EOF<br></div><div>}<br></div><div>EOF<br></div><div>-           echo "submenu '$(gettext_printf "Advanced options for %s" "${OS} $onstr" | grub_quote)' \$menuentry_id_option 'osprober-gnulinux-advanced-$boot_device_id' {"<br></div><div>-            is_top_level=false<br></div><div>- fi<br></div><div>-    title="${LLABEL} $onstr"<br></div><div>-        cat << EOF<br></div><div>-       menuentry '$(echo "$title" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-$LKERNEL-${recovery_params}-$boot_device_id' {<br></div><div>+               echo "submenu '$(gettext_printf "  Advanced options for %s" "${OS_SUBMENU} $onstr" | grub_quote)' \$menuentry_id_option 'osprober-gnulinux-advanced-$boot_device_id' {"<br></div><div>+         <br></div><div>+          PRIMARY_VALUES="$(menu_entry_values ${LINUX})"<br></div><div>+          # Stash the values (other than the displayed name) of the primary<br></div><div>+          # menu entry. <br></div><div>+         <br></div><div>+               is_top_level=false<br></div><div>+        fi<br></div><div>+<br></div><div>+        SUBMENU_VALUES="$(menu_entry_values ${LINUX})"<br></div><div>+        if [ "x${is_top_level}" = xfalse ] && \<br></div><div>+           [ "x${SUBMENU_VALUES}" != "x${PRIMARY_VALUES}" ]; then<br></div><div>+          # Allow only submenu entries that are different than their primary<br></div><div>+          # menu entry. <br></div><div>+<br></div><div>+          title="${OS} $onstr"<br></div><div>+          printf "Adding '%s' to submenu\n" "${OS}" >&2<br></div><div>+          cat << EOF<br></div><div>+  menuentry '$(echo "$title" | grub_quote)' --class gnu-linux --class gnu --class os \$menuentry_id_option 'osprober-gnulinux-$LKERNEL-${recovery_params}-$boot_device_id' {<br></div><div>EOF<br></div><div>- save_default_entry | sed -e "s/^/$grub_tab$grub_tab/"<br></div><div>-       printf '%s\n' "${prepare_boot_cache}" | grub_add_tab<br></div><div>-        cat <<  EOF<br></div><div>-                linux ${LKERNEL} ${LPARAMS}<br></div><div>+          save_default_entry | sed -e "s/^/$grub_tab$grub_tab/"<br></div><div>+          printf '%s\n' "${prepare_boot_cache}" | grub_add_tab<br></div><div>+          cat << EOF<br></div><div>+    linux ${LKERNEL} ${LPARAMS}<br></div><div>EOF<br></div><div>-        if [ -n "${LINITRD}" ] ; then<br></div><div>+          if [ -n "${LINITRD}" ] ; then<br></div><div>             cat << EOF<br></div><div>-         initrd ${LINITRD}<br></div><div>+    initrd ${LINITRD}<br></div><div>EOF<br></div><div>-        fi<br></div><div>-        cat << EOF<br></div><div>-       }<br></div><div>+          fi<br></div><div>+          cat << EOF<br></div><div>+  }<br></div><div>EOF<br></div><div>-   if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then<br></div><div>-            replacement_title="$(echo "Advanced options for ${OS} $onstr" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')"<br></div><div>-          quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"<br></div><div>-       title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"<br></div><div>-         grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")"<br></div><div>-  fi<br></div><div>+          if [ x"$title" = x"$GRUB_ACTUAL_DEFAULT" ] || [ x"Previous Linux versions>$title" = x"$GRUB_ACTUAL_DEFAULT" ]; then<br></div><div>+            replacement_title="$(echo "  Advanced options for ${OS} $onstr" | sed 's,>,>>,g')>$(echo "$title" | sed 's,>,>>,g')"<br></div><div>+            quoted="$(echo "$GRUB_ACTUAL_DEFAULT" | grub_quote)"<br></div><div>+            title_correction_code="${title_correction_code}if [ \"x\$default\" = '$quoted' ]; then default='$(echo "$replacement_title" | grub_quote)'; fi;"<br></div><div>+            grub_warn "$(gettext_printf "Please don't use old title \`%s' for GRUB_DEFAULT, use \`%s' (for versions before 2.00) or \`%s' (for 2.00 or later)" "$GRUB_ACTUAL_DEFAULT" "$replacement_title" "gnulinux-advanced-$boot_device_id>gnulinux-$version-$type-$boot_device_id")"<br></div><div>+          fi<br></div><div>+        fi<br></div><div>       done<br></div><div>       if [ x"$is_top_level" != xtrue ]; then<br></div><div>  echo '}'<br></div>