Skip to content

Instantly share code, notes, and snippets.

@ThinGuy
Created June 5, 2025 16:07
Show Gist options
  • Save ThinGuy/355686867e3e804f597851bd68c3ae49 to your computer and use it in GitHub Desktop.
Save ThinGuy/355686867e3e804f597851bd68c3ae49 to your computer and use it in GitHub Desktop.
Script to calculate all vs installed packages on Ubuntu
#!/bin/bash
# An Ubuntu Package Counter - Counts all vs installed and creates manifests by component for current release.
# Set parameters
export TITLE='AWS Summit Washington, DC 2025'
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; }
# This array is for main since the sections won't start with a component
declare -ag SECTIONS=(admin cli-mono comm database debug devel doc editors education electronics embedded fonts games gnome gnu-r gnustep graphics hamradio haskell httpd interpreters introspection java javascript kde kernel libdevel libs lisp localization mail math metapackages misc net news ocaml oldlibs otherosfs perl php python ruby rust science shells sound tasks tex text utils vcs video web x11 xfce zope)
# Cleanup old manifests
find ~/ -maxdepth 1 -type f -regextype "posix-extended" -iregex '.*ubuntu-.*\.(installed|all).manifest' -delete
# Begin output
printf "\n\e[1G\e[0;1;38;2;233;84;32mUbuntu Pro\e[0;1m™ Swag Script - ${TITLE}\e[0m\n\n\e[2G\e[1mSystem Info:\e[0m $(ubuntu-distro-info --series=${REL,,} -f)\n"
[[ -n ${MID} ]] && { printf "\e[2G\e[1mMachine ID:\e[0m\x20${MID}\n\n"; }
# Create arrays of all vs installed packages by component
printf "\e[2G\e[1mParsing APT components...\e[0m\n"
printf "\e[3G - Parsing \e[1mMain\e[0m\n"
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 "\e[3G - Parsing \e[1mUniverse\e[0m\n"
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 "\e[3G - Parsing \e[1mMultiverse\e[0m\n"
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 "\e[3G - Parsing \e[1mRestricted\e[0m\n"
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}'))
# Display Package Counts
printf "\n\e[2G\e[1mPackages by component (installed):\e[0m\n\n"
printf "\e[3G - Main: \e[1m${#MAIN_LIST_INSTALLED[@]}\e[0m\n"
printf "\e[3G - Universe: \e[1m${#UNIVERSE_LIST_INSTALLED[@]}\e[0m\n"
printf "\e[3G - Multiverse: \e[1m${#MULTIVERSE_LIST_INSTALLED[@]}\e[0m\n"
printf "\e[3G - Restricted: \e[1m${#RESTRICTED_LIST_INSTALLED[@]}\e[0m\n"
export TOTAL_INSTALLED=$((${#MAIN_LIST_INSTALLED[@]}+${#UNIVERSE_LIST_INSTALLED[@]}+${#MULTIVERSE_LIST_INSTALLED[@]}+${#RESTRICTED_LIST_INSTALLED[@]}))
printf "\n\e[2G\e[1mPackages by component (all):\e[0m\n\n"
printf "\e[3G - Main: \e[1m${#MAIN_LIST[@]}\e[0m\n"
printf "\e[3G - Universe: \e[1m${#UNIVERSE_LIST[@]}\e[0m\n"
printf "\e[3G - Multiverse: \e[1m${#MULTIVERSE_LIST[@]}\e[0m\n"
printf "\e[3G - Restricted: \e[1m${#RESTRICTED_LIST[@]}\e[0m\n"
export TOTAL_ALL=$((${#MAIN_LIST[@]}+${#UNIVERSE_LIST[@]}+${#MULTIVERSE_LIST[@]}+${#RESTRICTED_LIST[@]}))
printf "\n\e[2G\e[1mTotal Packages:\e[0m\n"
printf "\e[3G - Installed: \e[1m${TOTAL_INSTALLED}\e[0m\n"
printf "\e[3G - All: \e[1m${TOTAL_ALL}\e[0m\n"
# Create manifests
printf "\n\e[2G\e[1mCreating Package + Version manifests...\e[0m\n"
(printf '%s\n' ${MAIN_LIST[@]}|sed -r 's/\|/\t/g')| tee 1>/dev/null ~/ubuntu-${REL,,}_main_${DARCH}.all.manifest
(printf '%s\n' ${UNIVERSE_LIST[@]}|sed -r 's/\|/\t/g')| tee 1>/dev/null ~/ubuntu-${REL,,}_universe_${DARCH}.all.manifest
(printf '%s\n' ${MULTIVERSE_LIST[@]}|sed -r 's/\|/\t/g')| tee 1>/dev/null ~/ubuntu-${REL,,}_multiverse_${DARCH}.all.manifest
(printf '%s\n' ${RESTRICTED_LIST[@]}|sed -r 's/\|/\t/g')| tee 1>/dev/null ~/ubuntu-${REL,,}_restricted_${DARCH}.all.manifest
(printf '%s\n' ${MAIN_LIST_INSTALLED[@]}|sed -r 's/\|/\t/g')| tee 1>/dev/null ~/ubuntu-${REL,,}_main_${DARCH}.installed.manifest
(printf '%s\n' ${UNIVERSE_LIST_INSTALLED[@]}|sed -r 's/\|/\t/g')| tee 1>/dev/null ~/ubuntu-${REL,,}_universe_${DARCH}.installed.manifest
(printf '%s\n' ${MULTIVERSE_LIST_INSTALLED[@]}|sed -r 's/\|/\t/g')| tee 1>/dev/null ~/ubuntu-${REL,,}_multiverse_${DARCH}.installed.manifest
(printf '%s\n' ${RESTRICTED_LIST_INSTALLED[@]}|sed -r 's/\|/\t/g')| tee 1>/dev/null ~/ubuntu-${REL,,}_restricted_${DARCH}.installed.manifest
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[3G\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//')
printf "\n\e[4G\e[1mInstalled Packages:\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//')
# Print message that we are done
printf "\n\n\e[1G\e[0;1;38;2;233;84;32mUbuntu Pro\e[0;1m™\e[0m Swag Script Complete\e[0m\n\nThank you for visiting Canonical at ${TITLE%%,*}\x21\n\n"
# Clean up vars
unset $(grep -oP '(?<=^declare -ag |export )[^=]+' ${PROG}|paste -sd' ')
# Script complete.
exit 0
@ThinGuy
Copy link
Author

ThinGuy commented Jun 5, 2025

craigbender@cbpc:~$  ./aws-pro-counter.sh 

Ubuntu Pro™ Swag Script - AWS Summit Washington, DC 2025

 System Info: Ubuntu 25.04 "Plucky Puffin"
 Machine ID: b643c14980804fd7a70d3869389c8b11

 Parsing APT components...
   - Parsing Main
   - Parsing Universe
   - Parsing Multiverse
   - Parsing Restricted

 Packages by component (installed):

   - Main: 2388
   - Universe: 2108
   - Multiverse: 10
   - Restricted: 4

 Packages by component (all):

   - Main: 5915
   - Universe: 67234
   - Multiverse: 1095
   - Restricted: 267

 Total Packages:
   - Installed: 4510
   - All: 74511

 Creating Package + Version manifests...

  All Packages:

   - /home/craigbender/ubuntu-plucky_main_amd64.all.manifest
   - /home/craigbender/ubuntu-plucky_universe_amd64.all.manifest
   - /home/craigbender/ubuntu-plucky_multiverse_amd64.all.manifest
   - /home/craigbender/ubuntu-plucky_restricted_amd64.all.manifest

   Installed Packages:

   - /home/craigbender/ubuntu-plucky_main_amd64.installed.manifest
   - /home/craigbender/ubuntu-plucky_universe_amd64.installed.manifest
   - /home/craigbender/ubuntu-plucky_multiverse_amd64.installed.manifest
   - /home/craigbender/ubuntu-plucky_restricted_amd64.installed.manifest


Ubuntu Pro™ Swag Script Complete

Thank you for visiting Canonical at AWS Summit Washington!

@ThinGuy
Copy link
Author

ThinGuy commented Jun 5, 2025

craigbender@cbpc:~/$ ./aws-pro-counter-sh

Ubuntu Pro™ Swag Script - AWS Summit Washington, DC 2025

 System Info: Ubuntu 25.04 "Plucky Puffin"
 Machine ID: b643c14980804fd7a70d3869389c8b11

 Parsing APT components...
   - Parsing Main
   - Parsing Universe
   - Parsing Multiverse
   - Parsing Restricted

 Packages by component (installed):

   - Main: 2388
   - Universe: 2108
   - Multiverse: 10
   - Restricted: 4

 Packages by component (all):

   - Main: 5915
   - Universe: 67234
   - Multiverse: 1095
   - Restricted: 267

 Total Packages:
   - Installed: 4510
   - All: 74511

 Creating Package + Version manifests...

  All Packages:

   - /home/craigbender/ubuntu-plucky_main_amd64.all.manifest
   - /home/craigbender/ubuntu-plucky_universe_amd64.all.manifest
   - /home/craigbender/ubuntu-plucky_multiverse_amd64.all.manifest
   - /home/craigbender/ubuntu-plucky_restricted_amd64.all.manifest

   Installed Packages:

   - /home/craigbender/ubuntu-plucky_main_amd64.installed.manifest
   - /home/craigbender/ubuntu-plucky_universe_amd64.installed.manifest
   - /home/craigbender/ubuntu-plucky_multiverse_amd64.installed.manifest
   - /home/craigbender/ubuntu-plucky_restricted_amd64.installed.manifest


Ubuntu Pro™ Swag Script Complete

Thank you for visiting Canonical at AWS Summit Washington!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment