Created
June 20, 2025 22:30
-
-
Save ThinGuy/d34e43d650b55425522d4534886e3ddb to your computer and use it in GitHub Desktop.
An Ubuntu Package Counter - Counts all vs installed and creates manifests by component for the current release.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # An Ubuntu Package Counter - Counts all vs installed and creates manifests by component for the current release. | |
| # Set message | |
| export TITLE='\e[0;1;38;2;233;84;32mUbuntu Pro\e[0;1m™ Package Counter\e[0m' | |
| export GBMSG="Thank you for using \e[0;1;38;2;233;84;32mUbuntu\x21" | |
| # Parameters | |
| export PROG="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/${BASH_SOURCE[0]##*/}" | |
| export DARCH=$(dpkg --print-architecture) | |
| export REL=$(lsb_release -cs 2>/dev/null|sed 's/^.*$/\u&/') | |
| export VER=$(lsb_release -rs 2>/dev/null) | |
| [[ -f /etc/machine-id ]] && { export MID=$(cat /etc/machine-id); } | |
| [[ -z ${MID} && -f /var/lib/dbus/machine-id ]] && { export MID=$(cat /var/lib/dbus/machine-id); } | |
| [[ -z ${MID} ]] && { export MID=unknown; } | |
| # Begin output | |
| printf "\n\e[1G${TITLE}\e[0m\n\n\e[2G\e[1mSystem Info:\e[0m $(ubuntu-distro-info --series=${REL,,} -f) (${DARCH})\n" | |
| [[ -n ${MID} ]] && { printf "\e[2G\e[1mMachine ID:\e[0m\x20${MID}\n\n"; } | |
| printf "\e[2G\e[1mPreparing environment...\e[0m\n" | |
| printf "\r\e[K\r\e[3G - Removing any existing manifest.s..\e[K\r" | |
| # Cleanup old manifests | |
| find ~/ -maxdepth 1 -type f -regextype "posix-extended" -iregex '.*ubuntu-.*\.(installed|all).manifest' -delete | |
| printf "\r\e[K\r\e[3G - Updating APT caches...\e[K\r" | |
| sudo apt update &>/dev/null | |
| printf "\r\e[K\r\e[3G - Creating list of all APT sections...\e[K\r" | |
| # This array is for main since the sections won't start with a component | |
| declare -ag SECTIONS=($(apt -qq 2>/dev/null show \*|awk '/^Section/{gsub(/.*\//,"",$2);print $2}'|sort -uV)) | |
| # Create arrays of all vs installed packages by component | |
| printf "\e[2G\e[1mParsing APT components...\e[0m\n" | |
| printf "\r\e[3G - Parsing \e[1mMain\e[0m\e[K\r" | |
| declare -ag MAIN_LIST=($((printf '%s\n' ${SECTIONS[@]}|xargs -rn1 -P0 bash -c 'apt -qq 2>/dev/null list "?section(^$0$)"'|sed -r '/^$/d')|sort -uV|awk -F"/| " '{OFS="|";print $1,$3}')) | |
| declare -ag MAIN_LIST_INSTALLED=($((printf '%s\n' ${SECTIONS[@]}|xargs -rn1 -P0 bash -c 'apt -qq 2>/dev/null list --installed "?section(^$0$)"'|sed -r '/^$/d')|sort -uV|awk -F"/| " '{OFS="|";print $1,$3}')) | |
| printf "\r\e[3G - Parsing \e[1mUniverse\e[0m\e[K\r" | |
| declare -ag UNIVERSE_LIST=($((apt -qq 2>/dev/null list '?section(^universe/)'|sed -r '/^$/d')|sort -uV|awk -F"/| " '{OFS="|";print $1,$3}')) | |
| declare -ag UNIVERSE_LIST_INSTALLED=($((apt -qq 2>/dev/null list --installed '?section(^universe/)'|sed -r '/^$/d')|sort -uV|awk -F"/| " '{OFS="|";print $1,$3}')) | |
| printf "\r\e[3G - Parsing \e[1mMultiverse\e[0m\e[K\r" | |
| declare -ag MULTIVERSE_LIST=($((apt -qq 2>/dev/null list '?section(^multiverse/)'|sed -r '/^$/d')|sort -uV|awk -F"/| " '{OFS="|";print $1,$3}')) | |
| declare -ag MULTIVERSE_LIST_INSTALLED=($((apt -qq 2>/dev/null list --installed '?section(^multiverse/)'|sed -r '/^$/d')|sort -uV|awk -F"/| " '{OFS="|";print $1,$3}')) | |
| printf "\r\e[3G - Parsing \e[1mRestricted\e[0m\e[K\r" | |
| declare -ag RESTRICTED_LIST=($((apt -qq 2>/dev/null list '?section(^restricted/)'|sed -r '/^$/d')|sort -uV|awk -F"/| " '{OFS="|";print $1,$3}')) | |
| declare -ag RESTRICTED_LIST_INSTALLED=($((apt -qq 2>/dev/null list --installed '?section(^restricted/)'|sed -r '/^$/d')|sort -uV|awk -F"/| " '{OFS="|";print $1,$3}')) | |
| printf '\r\e[K\r\e[1A\e[K\r\e[2G\e[1mParsing APT components \e[0;1;38;2;0;255;0m✓\e[0m\e[2B\n' | |
| export TOTAL_INSTALLED=$((${#MAIN_LIST_INSTALLED[@]}+${#UNIVERSE_LIST_INSTALLED[@]}+${#MULTIVERSE_LIST_INSTALLED[@]}+${#RESTRITECTED_LIST_INSTALLED[@]})) | |
| export TOTAL_ALL=$((${#MAIN_LIST[@]}+${#UNIVERSE_LIST[@]}+${#MULTIVERSE_LIST[@]}+${#RESTRITECTED_LIST[@]})) | |
| # Display Package Counts | |
| (((printf "Component|Installed|Available\n─────────|─────────|─────────\n"; | |
| for i in main universe multiverse restricted;do | |
| eval printf '%s\|%s\|%s\\n' ${i} \$\{\#${i^^}_LIST_INSTALLED[@]\} \$\{\#${i^^}_LIST[@]\}; | |
| done; | |
| printf "|═════════|═════════\n\nTotals|${TOTAL_INSTALLED}|${TOTAL_ALL}")|column -ets"|")| \ | |
| sed -r 's/^/\x20\x20/g;s/Compon.*$|Totals.*$/'$(printf "\e[1m&\e[0m")'/g') | |
| # Create manifests | |
| printf "\n\e[2G\e[1mCreating Package + Version manifests...\e[0m\n" | |
| for i in main universe multiverse restricted;do | |
| printf "\r\e[3G - Creating \e[1mubuntu-${REL}_${i,,}_${DARCH}.installed.manifest\e[0m\e[K\r" | |
| eval printf '%s\\n' \$\{${i^^}_LIST_INSTALLED[@]\}|sed -r 's/\|/\t/g'| tee 1>/dev/null ~/ubuntu-${REL}_${i,,}_${DARCH}.installed.manifest; | |
| printf "\r\e[3G - Creating \e[1mubuntu-${REL}_${i,,}_${DARCH}.all.manifest\e[0m\e[K\r" | |
| eval printf '%s\\n' \$\{${i^^}_LIST[@]\}|sed -r 's/\|/\t/g'| tee 1>/dev/null ~/ubuntu-${REL}_${i,,}_${DARCH}.all.manifest; | |
| done; | |
| printf '\r\e[K\r\e[1A\e[K\r\e[2G\e[1mCreating Package + Version manifests \e[0;1;38;2;0;255;0m✓\e[0m\e[2B\n' | |
| declare -ag MANIFESTS=($((find ~/ -maxdepth 1 -type f -regextype "posix-extended" -iregex '.*ubuntu-.*\.(installed|all).manifest'|sort -uV)|sed -r '/main.*|universe.*/!H;//p;$!d;g;s/\n//')) | |
| # Show location of manifest files | |
| printf "\n\e[2G\e[1mInstalled Package Manifests:\e[0m\n\n" | |
| (printf '\e[3G - %s\n' ${MANIFESTS[@]}|sed -r '/\.all\.manifest/d'|sed -r '/main.*|universe.*/!H;//p;$!d;g;s/\n//') | |
| printf "\n\e[2G\e[1mAll Packages:\e[0m\n\n" | |
| (printf '\e[3G - %s\n' ${MANIFESTS[@]}|sed -r '/\.installed\.manifest/d'|sed -r '/main.*|universe.*/!H;//p;$!d;g;s/\n//') | |
| # Print message that we are done | |
| printf "\n\e[1G${TITLE} complete.\e[0m\n\n${GBMSG}\n\n" | |
| # Clean up vars | |
| unset MAIN_LIST* MULTIVERSE_LIST* UNIVERSE_LIST* RESTRICTED_LIST* MANIFESTS VER REL PROG EVENT DARCH TOTAL* TITLE SNAME GBMSG MID | |
| # Script complete. | |
| exit 0 |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Note: sudo is required to run apt update