检查并删除未使用的PPA。

自从安装以来,我在我的15.04系统中添加了不少PPA,因为我想要一个特定的应用程序。但有时候我又删除了那个软件包,因为它不起作用,不是我真正想要的,或者只是因为我不再需要它了。我不知道这是否有区别,但有些存储库是通过add-apt-repository安装的,而其他一些则是通过手动创建文件在/etc/apt/sources.list.d/目录下的命令来安装的。
现在我该如何检查是否安装了任何来自PPA的软件包,如果没有,则将其从我的软件源中删除?这个过程应该自动适用于所有的PPA。

作为独立脚本还是y-ppa-manager的扩展?; ) - A.B.
@A.B. 独立使用,谢谢。我不使用 y-ppa-manager - Byte Commander
3个回答

这是一个脚本。没有参数的情况下,脚本会列出一些信息。使用--delete参数,如果没有安装任何软件包,将删除list文件。
#!/usr/bin/env bash
for f in /etc/apt/sources.list.d/*.list; do
    grep -Po "(?<=^deb\s).*?(?=#|$)" "$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=$(sed -e '/^Package:/!d' -e 's/Package: \(.*\)$/\1/g' /var/lib/apt/lists/*"$USER"*"$PPA"*Packages | xargs dpkg -l 2>/dev/null | grep -c '^ii')
          echo "PPA: ppa:$USER/$PPA"
          echo "FILENAME: $f"
          echo "$packageCount package(s) installed"
          if [ "$packageCount" -eq 0 ] && [ "$1" == "--delete" ]; then
            sudo rm "$f" && echo "$f deleted"
          fi
          echo
        else 
          USER=$(cut -d/ -f3 <<< "$ENTRY")
          PPA=$(cut -d/ -f4 <<< "$ENTRY")
          packageCount=$(sed -e '/^Package:/!d' -e 's/Package: \(.*\)$/\1/g' /var/lib/apt/lists/*"$USER"*Packages | xargs dpkg -l 2>/dev/null | grep -c '^ii')
          echo "REPOSITORY: $USER/$PPA"
          echo "FILENAME: $f"
          echo "$packageCount package(s) installed"
          if [ "$packageCount" -eq 0 ] && [ "$1" == "--delete" ]; then
            sudo rm "$f" && echo "$f deleted" 
          fi
          echo
        fi
    done
done

将上面的代码复制到一个新文件中,例如:
mkdir -p ~/bin
nano ~/bin/checkPPAs

使脚本可执行
chmod +x ~/bin/checkPPAs

并运行它。
~/bin/checkPPAs

列出所有仓库及已安装软件包的数量。
使用以下命令开始脚本:
~/bin/checkPPAs --delete

删除列表文件。

我的系统上的示例输出

ENTRY: http://ppa.launchpad.net/webupd8team/y-ppa-manager/ubuntu vivid main
PPA: ppa:webupd8team/y-ppa-manager
FILENAME: /etc/apt/sources.list.d/webupd8team-ubuntu-y-ppa-manager-vivid.list
3 package(s) installed

ENTRY: http://ppa.launchpad.net/nilarimogard/webupd8/ubuntu vivid main
PPA: ppa:nilarimogard/webupd8
FILENAME: /etc/apt/sources.list.d/nilarimogard-ubuntu-webupd8-vivid.list
5 package(s) installed

ENTRY: http://ppa.launchpad.net/obsproject/obs-studio/ubuntu vivid main
PPA: ppa:obsproject/obs-studio
FILENAME: /etc/apt/sources.list.d/obsproject-ubuntu-obs-studio-vivid.list
1 package(s) installed

ENTRY: http://archive.getdeb.net/ubuntu vivid-getdeb apps
REPOSITORY: archive.getdeb.net/ubuntu vivid-getdeb apps
FILENAME: /etc/apt/sources.list.d/getdeb.list
7 package(s) installed

ENTRY: http://ppa.launchpad.net/psi-plus/ppa/ubuntu vivid main
PPA: ppa:psi-plus/ppa
FILENAME: /etc/apt/sources.list.d/psi-plus-ubuntu-ppa-vivid.list
15 package(s) installed

ENTRY: http://ppa.launchpad.net/libreoffice/ppa/ubuntu vivid main
PPA: ppa:libreoffice/ppa
FILENAME: /etc/apt/sources.list.d/libreoffice-ubuntu-ppa-vivid.list
24 package(s) installed

ENTRY: https://deb.nodesource.com/node_0.12 vivid main
REPOSITORY: deb.nodesource.com/node_0.12 vivid main
FILENAME: /etc/apt/sources.list.d/nodesource.list
1 package(s) installed

ENTRY: http://dl.google.com/linux/chrome/deb/ stable main
REPOSITORY: dl.google.com/linux
FILENAME: /etc/apt/sources.list.d/google-chrome.list
2 package(s) installed

ENTRY: http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu vivid main
PPA: ppa:gnome3-team/gnome3
FILENAME: /etc/apt/sources.list.d/gnome3-team-ubuntu-gnome3-vivid.list
273 package(s) installed

ENTRY: http://ppa.launchpad.net/noobslab/apps/ubuntu vivid main
PPA: ppa:noobslab/apps
FILENAME: /etc/apt/sources.list.d/noobslab-ubuntu-apps-vivid.list
0 package(s) installed

ENTRY: http://ppa.launchpad.net/ubuntuhandbook1/corebird/ubuntu vivid main
PPA: ppa:ubuntuhandbook1/corebird
FILENAME: /etc/apt/sources.list.d/ubuntuhandbook1-ubuntu-corebird-vivid.list
1 package(s) installed

ENTRY: http://ppa.launchpad.net/webupd8team/unstable/ubuntu vivid main
PPA: ppa:webupd8team/unstable
FILENAME: /etc/apt/sources.list.d/webupd8team-ubuntu-unstable-vivid.list
1 package(s) installed

ENTRY: http://download.mono-project.com/repo/debian wheezy main
REPOSITORY: download.mono-project.com/repo
FILENAME: /etc/apt/sources.list.d/mono-xamarin.list
166 package(s) installed

ENTRY: http://ppa.launchpad.net/otto-kesselgulasch/gimp-edge/ubuntu vivid main
PPA: ppa:otto-kesselgulasch/gimp-edge
FILENAME: /etc/apt/sources.list.d/otto-kesselgulasch-ubuntu-gimp-edge-vivid.list
5 package(s) installed

ENTRY: http://ppa.launchpad.net/numix/ppa/ubuntu vivid main
PPA: ppa:numix/ppa
FILENAME: /etc/apt/sources.list.d/numix-ubuntu-ppa-vivid.list
3 package(s) installed

ENTRY: http://ppa.launchpad.net/webupd8team/atom/ubuntu vivid main
PPA: ppa:webupd8team/atom
FILENAME: /etc/apt/sources.list.d/webupd8team-ubuntu-atom-vivid.list
1 package(s) installed

ENTRY: https://packages.graylog2.org/repo/debian/ trusty 1.0
REPOSITORY: packages.graylog2.org/repo
FILENAME: /etc/apt/sources.list.d/graylog.list
3 package(s) installed

ENTRY: http://ppa.launchpad.net/ubuntu-mate-dev/ppa/ubuntu vivid main
PPA: ppa:ubuntu-mate-dev/ppa
FILENAME: /etc/apt/sources.list.d/ubuntu-mate-dev-ubuntu-ppa-vivid.list
0 package(s) installed

ENTRY: http://ppa.launchpad.net/gnome3-team/gnome3-staging/ubuntu vivid main
PPA: ppa:gnome3-team/gnome3-staging
FILENAME: /etc/apt/sources.list.d/gnome3-team-ubuntu-gnome3-staging-vivid.list
268 package(s) installed

ENTRY: http://debian.koha-community.org/koha stable main
REPOSITORY: debian.koha-community.org/koha stable main
FILENAME: /etc/apt/sources.list.d/koha.list
0 package(s) installed

ENTRY: http://ppa.launchpad.net/pgavin/ghdl/ubuntu trusty main
PPA: ppa:pgavin/ghdl
FILENAME: /etc/apt/sources.list.d/pgavin-ubuntu-ghdl-vivid.list
0 package(s) installed

ENTRY: http://ppa.launchpad.net/ubuntu-mate-dev/vivid-mate/ubuntu vivid main
PPA: ppa:ubuntu-mate-dev/vivid-mate
FILENAME: /etc/apt/sources.list.d/ubuntu-mate-dev-ubuntu-vivid-mate-vivid.list
3 package(s) installed

ENTRY: http://ppa.launchpad.net/webupd8team/sublime-text-3/ubuntu vivid main
PPA: ppa:webupd8team/sublime-text-3
FILENAME: /etc/apt/sources.list.d/webupd8team-ubuntu-sublime-text-3-vivid.list
1 package(s) installed

ENTRY: http://ppa.launchpad.net/webupd8team/java/ubuntu vivid main
PPA: ppa:webupd8team/java
FILENAME: /etc/apt/sources.list.d/webupd8team-ubuntu-java-vivid.list
1 package(s) installed

ENTRY: http://dl.google.com/linux/chrome/deb/ stable main
REPOSITORY: dl.google.com/linux
FILENAME: /etc/apt/sources.list.d/google.list
2 package(s) installed

ENTRY: http://dl.google.com/linux/chrome/deb/ stable main
REPOSITORY: dl.google.com/linux
FILENAME: /etc/apt/sources.list.d/google-chrome-beta.list
2 package(s) installed

你为什么认为移除它们是个坏主意?你更倾向于如何移除呢?使用 add-apt-repository --remove 命令?还是手动删除 ???.list 文件?那么这个 PPA 使用的 GPG 密钥会被一并移除吗,如果我使用 add-apt-repository --remove 呢? - Byte Commander
如果没有安装任何软件包,那么该文件可以安全删除。我将进行添加。删除密钥会稍微复杂一些。 - A.B.
我已经更新了我的脚本。 - A.B.
重新开始吧,一个rm命令中有一个echo - A.B.
/home/yoesoff/removeppa.sh:4:/home/yoesoff/removeppa.sh:语法错误:重定向意外 - Yusuf Ibrahim
太棒了!有没有办法识别哪个缺少 GPG 密钥,从而导致每次调用 add-apt-repository ppa 都变慢?在这种情况下通常会出现错误:Error: retrieving gpg key timed out - matt525252
你所说的“list文件”是什么意思并不清楚。从代码中我可以理解,它将只删除所有已安装0个软件包的文件,无论是否为ppa,但在你的措辞中并不清楚。 - Madacol
请注意,脚本无法正确解析没有路径的URL条目。例如,我的Spotify PPA列表如下:deb http://repository.spotify.com stable non-free。我已经安装了Spotify,但是脚本无法正确检测到这一点。 - Jurrie
1等一下。这个程序读取“list”文件并遍历每个条目。所以如果任何一个条目中没有安装任何软件包,它会删除整个文件?如果是这样的话,使用起来非常不安全。我有什么地方理解错了吗? - timuçin
1@timuçin,我看到你对答案提出的修改意见,但这些修改已经足够大,以至于我认为你应该单独撰写一篇回答(并在其中给予本答案的致谢和更正),详细说明你的担忧和解决方案。如果有其他人能够审查并确认你的修改,那就太好了,但我认为将其作为一个独立的回答更有可能引起关注。 - NotTheDr01ds
@A.B. 我跳过了审查这个建议的编辑,但我希望你能看一下,以防它是一个好的编辑。 - karel

我不知道有没有自动的方法,但这个方法相当快速:
1. 打开Synaptic软件包管理器,并在提示时输入密码。 2. 在左侧栏底部,点击“来源”。
现在,您系统中的所有ppa都将列在左侧栏的顶部。您可以逐个查看列表,看是否安装了任何软件(如果有的话,在右侧栏的软件名称旁边会有一个绿色框)。如果从ppa安装了许多软件(屏幕上无法一次显示),您可以点击右侧栏顶部的“S”来按状态对它们进行排序。
注意:如果您有任何未使用的ppa:
1. 点击顶部菜单中的“设置”。 2. 然后选择“存储库”。 3. “软件和更新”窗口将显示出来。 4. 从该窗口中,您可以在“其他软件”选项卡中删除未使用的ppa。

他问如何检测未使用的PPA。关于如何通过软件更新删除PPA的指南已经有很多了。 - Joe C
@JoeC 我不确定你在抱怨什么或为什么给我的回答投了反对票。它可能不是最好的方法,但我确实展示了如何检测未使用的PPA。 - Organic Marble

在看到被接受的答案有一个关键错误后,我不得不修复它并在这里发布。 A.B的答案遍历每个list文件中的条目,如果该文件中的任何条目在系统上安装的软件包数量为0,无论有多少条目有软件包,都会将整个文件删除。
它还完全忽略了与预定义格式不匹配的任何条目。它不会考虑它们。
此外,脚本只处理匹配的条目。它不会对空文件进行任何操作。
所以我修复了脚本,如下所示:
#!/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

使用方法完全相同,只是--delete选项仅在没有任何已安装软件包的条目和无法识别的条目时才删除文件。空白和注释行不计入条目。 即使我已经考虑了所有可能,这仍然是一个未经测试的、需要以sudo权限运行的脚本,请先备份/etc/apt/sources.list.d目录中的所有内容。

1如果你想修正一个已有的答案,你应该建议进行编辑。 - muru
你说得对。我会在提出修改建议后删除这个回答(如果我能的话)。 - timuçin
编辑被批准后 - timuçin
2@timuçin 哈哈 - 这次你赢不了了,对吧?我看到你的编辑了,但我建议它应该是一个独立的答案。 - NotTheDr01ds
@muru 我看到了 timuçin的编辑,但我没有采纳它,因为我觉得(a)它对原帖进行了太多改动,让人不舒服,而且(b)我没有能力(或时间)亲自确认。然而,最终它被其他两位审阅者拒绝了。我很想知道你在看完这个编辑后的想法。我们应该推动批准对现有答案的修改,还是将其作为一个新答案呢? - NotTheDr01ds