apt
を使用して手動でインストールされたパッケージを表示するには、次のような多くの方法があります。
apt-mark showmanual
しかし、その出力が多すぎる場合があります。たとえば、ユーザーが手動でパッケージfoo
をインストールした場合:
apt-get install foo
...そしてfoo
はbar
とbaz
に依存し、次にapt-mark showmanual
は出力します:
bar
baz
foo
トップレベルの手動でインストールされたパッケージ(iefoo
)だけを、依存関係なしでリストするにはどうすればよいですか(ie not baz
、またはbar
)?
次のコードは機能しているようですが、[〜#〜] gnu [〜#〜]parallel
Calling apt-rdepends
数百回は遅すぎます(4コアCPUで3時間):
apt-mark showmanual |
tee /tmp/foo |
parallel "apt-rdepends -f Depends,PreDepends,Suggests,Recommends {} |
tail +2" 2> /dev/null |
tr -s ' ' '\n' |
grep -v '[():]' |
sort -Vu |
grep -wv -f - /tmp/foo
これは、Python apt APIを使用して実行できます。_apt-mark showmanual
_に表示されるパッケージは、_is_installed
_がtrueであるapt.cache.Cache()
内のパッケージとまったく同じですおよび _is_auto_installed
_ はfalseですが、依存関係を処理する方が簡単です。
_#! /usr/bin/env python3
from apt import cache
manual = set(pkg for pkg in cache.Cache() if pkg.is_installed and not pkg.is_auto_installed)
depends = set(dep_pkg.name for pkg in manual for dep in pkg.installed.get_dependencies('PreDepends', 'Depends', 'Recommends') for dep_pkg in dep)
print('\n'.join(pkg.name for pkg in manual if pkg.name not in depends))
_
これでも、そこには表示されないはずのパッケージがいくつかリストされています(init
、grep
?!).
次のシェルスクリプトは、インストールされているすべての依存関係の親を検索します。
function get_installed_packages() {
apt list --installed | sed 's#/.*##'
}
function get_installed_packages_with_deps() {
dpkg-query --show --showformat '${Package} ${Depends} \
${Pre-Depends}\n' $(get_installed_packages) |
sed 's/ ([^(]*)//g; s/:any\|,//g'
}
function get_package_relations() {
awk '{print $1 " " $1; for(i = 2; i <= NF; i++) print $1 " " $i;}'
}
function add_marker() {
echo "~ ~"
}
function resolve_parents() {
tsort | sed -n '1,/~/ p' | head -n -1
}
(get_installed_packages_with_deps | get_package_relations; add_marker) |
resolve_parents
このスクリプトではtsort
を使用しました。依存関係のない最後にマーカーを追加すると、マーカーは結果に依存関係のない最後のエントリになると思います。したがって、依存関係のない最後のパッケージと依存関係のある最初のパッケージを区別できます。
この解決策には1つの問題があることに気づきました。
ディペンデンシーグラフに循環があります。これらのエントリはtsort
によって無視されます。
次のように、第1レベルの依存関係なしで手動でインストールされたすべてのパッケージを見つけることができます。
apt-mark showmanual | sort > manually-installed.txt
apt show $(apt-mark showmanual) 2>/dev/null |
grep -e ^Depends -e ^Pre-Depends > deps1.txt
cat deps1.txt |
sed 's/^Depends: //; s/^Pre-Depends: //;
s/(.*)//g; s/:any//g' > deps2.txt
cat deps2.txt | tr -d ',|' | tr ' ' '\n' | grep -v ^$ |
sort -u > all-dep-packages.txt
grep -v -F -f all-dep-packages.txt manually-installed.txt
次のワンライナーマジックを使用することもできます。
apt-mark showmanual | sort | grep -v -F -f <(apt show $(apt-mark showmanual) 2> /dev/null | grep -e ^Depends -e ^Pre-Depends | sed 's/^Depends: //; s/^Pre-Depends: //; s/(.*)//g; s/:any//g' | tr -d ',|' | tr ' ' '\n' | grep -v ^$ | sort -u)