Перерахуйте встановлені вручну пакети без їх залежностей


12

Існує багато способів показу пакетів, встановлених вручну за допомогою apt, таких як:

apt-mark showmanual

Але іноді цей вихід занадто великий. Наприклад, якщо користувач встановив пакет вручну foo:

apt-get install foo

... і fooзалежав від, barа bazпотім apt-mark showmanualвиводить:

bar
baz
foo

Як ми можемо перерахувати лише встановлені вручну пакети ( тобто foo ) без їх залежностей ( тобто ні baz, ні bar)?


Наступний код, здається, працює, але виклик GNU кілька сотень разів занадто повільний (три години з 4-ядерним процесором):parallelapt-rdepends

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

Хм. Відповіді та код OP все настільки різні, і повертають дещо інші дані, що я отримую трохи нечіткі відомості про те, які дані методу є найбільш правильними. Можливо, потрібна відповідь опитування, починаючи з мінімальної системи тестування та додаючи програми кілька разів, щоб побачити, як і коли змінюються результати.
agc

Відповіді:


9

Це можна зробити за допомогою API Apt Python. Пакети, які ви бачите в, - apt-mark showmanualце саме ті, в apt.cache.Cache()яких is_installedвірно і is_auto_installedнеправдиво. Але простіше обробити залежності:

#! /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?!).


У моїй системі , що код не виводить супернабір мого 3-годинний код, але шоу не дивують , як initі grep(може бути , ваш схильний дані корумпований?), І це показує дуже багато бібліотек. ОТОГ, мій 3-годинний код пропускає декілька предметів, які повинні бути там, елементи, які pythonнадрукує вищевказаний код. Можливо, відсутні елементи не були встановлені apt.
agc

@agc, мабуть, тому, що я не повторювався. Я спробую рекурсивний варіант після вихідних. Навіть із рекурсією, однак, я б очікував, що це буде набагато швидше, ніж викликати apt-rdepends кілька разів
muru

Вищеописаний pythonкод у 3600 разів швидший (тобто на це пішло 3 секунди), ніж мій код (3 години). З нетерпінням чекаю тестування рекурсивної версії ...
agc

3

Наступний скрипт оболонки шукає батьків усіх встановлених залежностей.

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у цьому сценарії. Я припускаю, що додаючи маркер в кінці без залежностей, маркер також буде останнім записом без залежностей у моєму результаті. Тож я можу розрізняти останній пакет без залежностей і перший пакет із залежностями.

Я помітив одну проблему з цим рішенням:
У графіку залежності є цикли. Ці записи ігноруються tsort.


2

Ви можете знайти всі встановлені вручну пакети без їх першого рівня залежності:

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)

Набагато швидше. Це виводить те, що здебільшого є набором коду OP, але він також не вистачає кількох, наприклад dasherпакет. У моїй системі код OP проходить через sort -Vвиходи 475 рядків, код Муру виводить 914 рядків (у тому числі dasher), а код відповіді - 995 рядків.
agc

Так, мій сценарій не враховує повне дерево залежності. Ви можете спробувати адаптувати його для більш високих рівнів ієрархії.
мореплавець
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.