After seeing the accepted answer having a crucial error, I had to fix it and post it here.
A.B's answer iterates over the entries in each list
file and if ANY of the entries in that file has 0 packages installed on the system, regardless of how many entries have packages, it removes the entire file.
It also completely disregards any entry that doesn't match a predefined format. It will not take them into account.
Also the script works with the entries matched. It leaves the empty files untouched.
So I fixed the script like so:
#!/usr/bin/env bash
for f in /etc/apt/sources.list.d/*.list; do
fileTotal=0
echo "FILENAME: $f"
while read -r ENTRY ; do
echo "ENTRY: $ENTRY"
# Sanitize entry line by removing stuff between square brackets
ENTRY=$(echo "$ENTRY" | sed 's/\[.*\] //')
HOST=$(cut -d/ -f3 <<< "$ENTRY")
if [ "ppa.launchpad.net" = "$HOST" ]; then
USER=$(cut -d/ -f4 <<< "$ENTRY")
PPA=$(cut -d/ -f5 <<< "$ENTRY")
packageCount=$(awk '$1=="Package:" {if (a[$2]++ == 0) {system("dpkg -l "$2)}}' /var/lib/apt/lists/*"$USER"*"$PPA"*Packages 2>/dev/null | awk '/^ii/' | wc -l)
else
USER=$(cut -d/ -f3 <<< "$ENTRY")
PPA=$(cut -d/ -f4 <<< "$ENTRY")
packageCount=$(awk '$1=="Package:" {if (a[$2]++ == 0) {system("dpkg -l "$2)}}' /var/lib/apt/lists/*"$USER"*Packages 2>/dev/null | awk '/^ii/' | wc -l)
fi
((fileTotal+=packageCount))
printf '\t%s\n' "REPOSITORY: $USER/$PPA"
printf '\t%s\n' "$packageCount package(s) installed"
echo
done < <(grep -Po "(?<=^deb\s).*?(?=#|$)" "$f")
# unrecognizedCount=$(grep -Pv "(?=^deb\s)|(?=^#).*" "$f" | grep -Pc "[^\s]")
unrecognizedCount=0
while read -r ENTRY ; do
((unrecognizedCount++))
printf '\t%s\n' "Unrecognized entry: $ENTRY"
done < <(grep -Pv "(?=^deb\s)|(?=^#).*" "$f" | grep -P "[^\s]")
echo "$fileTotal packages installed"
echo "$unrecognizedCount entries unrecognized"
if [ "$fileTotal" -eq 0 ] && [ "$unrecognizedCount" -eq 0 ]; then
if [ "$1" == "--delete" ]; then
sudo rm "$f"
sudo rm "$f".*
echo "$f deleted"
else
echo "Deletable"
fi
fi
echo "----------------------------"
done
The usage is exactly the same except --delete
option only deletes a file if there's no entry with any installed packages and no unrecognized entries. Blank and commented lines don't count as entries.
Even having considered everything I can, this is still not tested, safe script to run with sudo
privileges. Please backup everything in the /etc/apt/sources.list.d
directory.
y-ppa-manager
.