Skip to content

wupdate

One of my first Gentoo related scripts to portage more easily from the command line interface in a clear and efficient way


wupdate)

wupdate.sh

```bash

!/bin/bash

Ensure strict error handling where applicable, though we look at individual commands in the select loop

set -f # Disable globbing globally if needed, or handle locally. Leaving standard flags safe.

DISTRO="\((awk -F= '\)1=="ID"{gsub(/["'\'']/, "", \(2); print tolower(\)2)}' /etc/os-release)"

if [[ "$DISTRO" != "gentoo" ]]; then echo "This is not Gentoo, please go install Gentoo to be able to run this script.." exit 1 fi

COLUMNS="100"

banner() { echo -e "\e[0;35m" echo -e "██╗ ██╗██╗ ██╗██████╗ ██████╗ █████╗ ████████╗███████╗" echo -e "██║ ██║██║ ██║██╔══██╗██╔══██╗██╔══██╗╚══██╔══╝██╔════╝" echo -e "██║ █╗ ██║██║ ██║██████╔╝██║ ██║███████║ ██║ █████╗ author: wuseman" echo -e "██║███╗██║██║ ██║██╔═══╝ ██║ ██║██╔══██║ ██║ ██╔══╝ created: 2008-03-01" echo -e "╚███╔███╔╝╚██████╔╝██║ ██████╔╝██║ ██║ ██║ ███████╗" echo -e " ╚══╝╚══╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝" echo -e "This tool facilitates working with Portage on Gentoo" echo -e "------------------------------------------------------------\e[0m" } banner

if [[ "$EUID" -ne 0 ]]; then echo -e "\n You must run this tool as root\n" exit 1 fi

Dynamically resolve portage base directory

PORTDIR="$(portageq get_repo_path / gentoo 2>/dev/null || echo "/var/db/repos/gentoo")"

PS3=" Option: "

options=( "Sync Portage Tree" "Upgrade Whole System" "Update Packages With New Useflags" "List Upgradeable Packages" "Add Packages That Wont Be Removed By Depclean" "Emerge All Packages In A Category" "Make Configuration File(s) Up To Date" "Preserved Rebuild" "Reverse Dynamic Library Dependency" "Fix Static Library" "Uninstall Useless Packages" "Remove All Distfiles" "List All Binarys In Portage Tree" "Re-emerge All Ebuilds With Missing Files" "List All Useflags Not In Use And In Use" "Calculates The Total Time I'd Compiled All Packages" "How Many Percents Of All Avaliable Packages In Tree Are Installed" "Search For Modules I Have Enabled In Kernel" "View Emerge Log By Date In A Human Friendly Way" "Compare Global Useflags With A Profile Useflag" "Get The Size Of All Installed Packets Sorted By Size" "Find Installed Packages That Are Not In The Portage Tree Anymore" "Find Wich Useflags A Specifik Package Use With Desc" "Find Wich Packages Belongs To A Package" "Short Information About Loaded Kernel Modules" "Print A List Of Installed Perl Modules" "Upgrade All Perl Modules Via CPAN" "List All Available Python Modules" "Figure Out If A Command Is An Alias, Function Or Shell Builtin" "View Emerged Packages By Time From Bottom To Top" "Preview All Packages That Has Been Installed From An Overlay" "List All Overlays One By One To Get A Good Overview" "Find Out How Long Time It Toke To Build A Specifik Package" "Find all packages with a specifk useflag" "Print when you ran emerge last time" "Print All Options Again" "Quit" )

select opt in "\({options[@]}"; do case "\)opt" in "Sync Portage Tree") echo -e "\nPlease wait, syncing portage...\n" if command -v eix-sync &>/dev/null; then eix-sync else emerge --sync && eix-update fi echo -e "\nPortage has been successfully updated..\n" exit 0 ;;

"Upgrade Whole System")
    echo -e "\nPlease wait, searching for new packages to upgrade...\n"
    emerge -vuDN --with-bdeps y --keep-going @world
    echo -e "\nPortage packages were successfully upgraded...\n\n"
    exit 0
    ;;

"Update Packages With New Useflags")
    echo -e "\nPlease wait, searching for packages which need new use flags...\n"
    emerge --exclude openssl --exclude cryptsetup --ask --changed-use --update --deep --newuse @world
    echo -e "\nPortage packages were successfully upgraded...\n\n"
    exit 0
    ;;

"List Upgradeable Packages")
    eix --installed --upgrade | grep -o '\[U].*'
    ;;

"Add Packages That Wont Be Removed By Depclean")
    read -r -p "Package That You Want Not To Be Replaced: " noreplacepackage
    if [[ -n "$noreplacepackage" ]]; then
        emerge --noreplace "$noreplacepackage"
    fi
    exit 0
    ;;

"Emerge All Packages In A Category")
    read -r -p "Category (e.g. net-ftp): " categorytoinstall
    if [[ -d "$PORTDIR/$categorytoinstall" ]]; then
        for p in "$PORTDIR/$categorytoinstall"/*; do
            # Use native Bash parameter expansion instead of calling basename
            emerge --ask "$categorytoinstall/${p##*/}"
        done
    else
        echo "Category not found."
    fi
    exit 0
    ;;

"Make Configuration File(s) Up To Date")
    etc-update
    dispatch-conf
    exit 0
    ;;

"Preserved Rebuild")
    emerge @preserved-rebuild
    exit 0
    ;;

"Reverse Dynamic Library Dependency")
    revdep-rebuild
    exit 0
    ;;

"Fix Static Library")
    if command -v lafilefixer &>/dev/null; then
        lafilefixer --justfixit | grep -v skipping
    else
        echo "lafilefixer not found."
    fi
    exit 0
    ;;

"Uninstall Useless Packages")
    emerge --ask --depclean
    ;;

"Remove All Distfiles")
    eclean -d distfiles
    exit 0
    ;;

"List All Binarys In Portage Tree")
    echo -e "\nPlease wait while searching for binary packages...\n"
    find "$PORTDIR/" -type d -name "*-bin" | awk -F'/' '{print $NF}' | sort
    echo ""
    read -r -p "Binary Package To Compile (Ctrl+C to quit): " compile
    if [[ -n "$compile" ]]; then
        emerge --ask "$compile"
    fi
    exit 0
    ;;

"Re-emerge All Ebuilds With Missing Files")
    # Highly optimized pipeline to find missing files and trigger rebuilds
    emerge -av1 $(qlist --installed --nocolor | uniq | while read -r cp; do
        qlist --exact "$cp" | while read -r file; do
            if [[ ! -e "$file" ]]; then
                echo "$cp"
                echo "$cp: missing $file" >&2
                break
            fi
        done
    done)
    ;;

"List All Useflags Not In Use And In Use")
    # Rewritten logic to cleanly dump and sort current usage profiles
    emerge -epv world | grep USE | cut -d '"' -f 2 | tr ' ' '\n' | grep -v '[()]*' | sort -u > use
    grep '^-' use | sed 's/^-//' | tr '\n' ' ' > notuse
    sed -i '/^-/d' use
    tr '\n' ' ' < use > tmp_use && mv tmp_use use
    echo "Files 'use' and 'notuse' generated."
    exit 0
    ;;

"Calculates The Total Time I'd Compiled All Packages")
    echo -e "\nPlease wait while I count...\n"
    total_compile_time="$(qlist -I | xargs qlop -t | awk '{secs += $2} END { printf("%dh:%dm:%ds\n", secs / 3600, (secs % 3600) / 60, secs % 60); }')"
    echo -e "You have compiled packages in a total time of \e[1;32m$total_compile_time\e[0m.\n"
    exit 0
    ;;

"How Many Percents Of All Avaliable Packages In Tree Are Installed")
    # Fixed math layout to protect against division by zero
    local_installed=$(eix --only-names -I | wc -l)
    total_available=$(eix --only-names | wc -l)
    if [[ $total_available -gt 0 ]]; then
        percent_gentoo=$(( local_installed * 100 / total_available ))
        echo -e "\nYou have installed \e[1;32m$percent_gentoo%\e[0m of all available packages.\n"
    fi
    exit 0
    ;;

"Search For Modules I Have Enabled In Kernel")
    read -r -p "Search For Module: " module_kernel
    if [[ -n "$module_kernel" ]]; then
        # Fixed single quotes preventing variable evaluation
        echo -e "\nYou built Kernel With Following Modules: \n"
        find /lib/modules/*/ -name "*${module_kernel}*" | awk -F'/' '{print $NF}'
    fi
    exit 0
    ;;

"View Emerge Log By Date In A Human Friendly Way")
    awk -F: '{print strftime("%Y-%m-%d -> %X --> ", $1),$2}' /var/log/emerge.log
    ;;

"Compare Global Useflags With A Profile Useflag")
    echo "Feature under construction. Check configuration manually."
    ;;

"Get The Size Of All Installed Packets Sorted By Size")
    GREEN='\033[01;32m' WHITE='\033[0;37m'
    qsize | cut -d'/' -f2 | awk -v g="$GREEN" -v w="$WHITE" '{print w$1,g$6}' | sort -n -k 9
    exit 0
    ;;

"Find Installed Packages That Are Not In The Portage Tree Anymore")
    for f in $(qlist -IC); do
        if [[ ! -d "$PORTDIR/$f" ]]; then
            echo "$f is no longer in the portage tree"
        fi
    done
    exit 0
    ;;

"Find Wich Useflags A Specifik Package Use With Desc")
    read -r -p "Package For View Useflags: " useflags_equeryu
    if [[ -n "$useflags_equeryu" ]]; then
        equery u "$useflags_equeryu"
    fi
    exit 0
    ;;

"Find Wich Packages Belongs To A Package")
    read -r -p "Package to look up file ownership for: " useflags_equeryb
    if [[ -n "$useflags_equeryb" ]]; then
        equery b "$useflags_equeryb"
    fi
    exit 0
    ;;

"Short Information About Loaded Kernel Modules")
    # Fixed parsing to cleanly extract metadata from active modules
    modinfo $(cut -d' ' -f1 /proc/modules) 2>/dev/null | sed '/^dep/s/$/\n/; /^file\|^desc\|^dep/!d'
    exit 0
    ;;

"Print A List Of Installed Perl Modules")
    echo -e "\nPlease wait while searching for installed Perl modules...\n"
    perl -MExtUtils::Installed -e '$inst = ExtUtils::Installed->new(); @modules = $inst->modules(); print join("\n", @modules);'
    echo ""
    exit 0
    ;;

"Upgrade All Perl Modules Via CPAN")
    perl -MCPAN -e 'CPAN::Shell->install(CPAN::Shell->r)'
    exit 0
    ;;

"List All Available Python Modules")
    python -c "help('modules')"
    exit 0
    ;;

"Figure Out If A Command Is An Alias, Function Or Shell Builtin")
    read -r -p "Command To Check: " cmd_check
    if [[ -n "$cmd_check" ]]; then
        type "$cmd_check"
    fi
    exit 0
    ;;

"View Emerged Packages By Time From Bottom To Top")
    if ! command -v genlop &>/dev/null; then
        echo -e "${0##*/}: internal error -- genlop is required, exiting..."
        exit 1
    else
        echo -e "Please wait, this might take some time..."
        genlop -l
    fi
    exit 0
    ;;

"Preview All Packages That Has Been Installed From An Overlay")
    eix -c --installed-overlay
    exit 0
    ;;

"List All Overlays One By One To Get A Good Overview")
    emerge --info --verbose | sed -n '/^Repo/,/^ABI/p' | head -n -1
    exit 0
    ;;

"Find Out How Long Time It Toke To Build A Specifik Package")
    read -r -p "Package: " packagetime
    if [[ -n "$packagetime" ]]; then
        raw_seconds=$(qlist -I | xargs qlop -t | grep "$packagetime" | awk '{print $2}' | head -n 1)
        if [[ -n "$raw_seconds" ]]; then
            echo "scale=2; $raw_seconds / 60" | bc
        else
            echo "Package not found in compilation logs."
        fi
    fi
    exit 0
    ;;

"Find all packages with a specifk useflag")
    if [[ -n "$1" ]]; then
        q use "+$1"
    else
        read -r -p "Enter useflag: " target_flag
        q use "+$target_flag"
    fi
    ;;

"Print when you ran emerge last time")
    grep "emerge on" /var/log/emerge.log | cut -d: -f2,3,4,5,6 | tr '[:upper:]' '[:lower:]' | sed 's/ started/You ran/g' | tail -n 1
    ;;

"Print All Options Again")
    # Kill current selection session to allow loop to re-print options dynamically
    continue
    ;;

"Quit")
    break
    ;;

*)
    echo -e "\n\nPlease choose a valid option from the menu.\n"
    ;;
esac

done ```

Extra

Example - Search for sound-related kernel modules

find /lib/modules/*/ -name "*snd*"

The system set, also referred to as @system in Portage development, contains the software packages required for a standard Gentoo Linux installation to run properly

emerge --pretend @system

The system packages are defined by the Gentoo profiles (through the packages files)

An end-user can easily see which packages are seen as part of the system set by running the following emerge command:

firefox="$(qlist -I | xargs qlop -t | grep firefox | awk '{print $2}')"; echo $firefox / 60 | bc

Show all globally disabled USE flags

eix --print-all-useflags | grep -E '^-[-a-z0-9]+$'