apt-get remove avec le wildcard enlevé bien plus que prévu. Pourquoi?

38

La nuit dernière, j'essayais de graver des CD. Étant contrarié par k3b et choisissant plutôt d’utiliser brasero, j’ai décidé de supprimer k3b.

J'ai tapé dans:

sudo apt-get remove k3b

J'ai frappé l'onglet deux fois et j'ai vu que j'avais à la fois des données k3b et k3b sur mon système. En supposant que je n'aurais pas besoin de k3b-data sur mon système sans k3b, je voulais aussi le supprimer, aussi j'ai entré:

sudo apt-get remove k3b*

Malheureusement, je frappe Y pour confirmer sans regarder. Il a désinstallé beaucoup plus que k3bet k3b-data. Il a désinstallé les paquets qui ne correspondaient pas à ma k3b*regex. Par exemple: transmissionet network-manager.

Je suis à peu près certain que je n'ai pas d'espace entre k3bet *mais je ne sais pas pourquoi sinon cela supprimerait tout ce qu'il a fait. Y a-t-il quelque chose à propos d'apt-get que je me suis mal compris?

Steve Goykovich
la source

Réponses:

38

La commande que vous voulez est sudo apt-get remove '^k3b.*'parce que:

  • Vous devez .*faire correspondre n'importe quel caractère, n'importe quel nombre de fois
  • Vous devez ^faire correspondre le début de la chaîne
  • Vous devez citer l'expression rationnelle pour empêcher bash de l'interpréter *comme un caractère générique.

(Cette réponse complète et résume les informations précédentes fournies par qbi et Flimm)

Boris Dalstein
la source
5
C’est sûr et vous pouvez l’utiliser, mais vous n’avez pas besoin du .*. Vous pouvez simplement utiliser sudo apt-get remove ^k3b. La présence de ^est suffisante pour provoquer l'argument à interpréter comme une expression régulière, et quand aptou apt-getinterprète un argument comme une expression régulière, il lui correspond partout dans le nom du package. C'est pourquoi vous avez besoin ^- d' ancrer la correspondance au début du nom du paquet. L'expression régulière n'a pas besoin de correspondre au nom complet du package, à n'importe quelle partie de celui-ci.
Eliah Kagan
1
@EliahKagan Thx pour l'info supplémentaire! (et en effet, il est logique que si vous avez besoin ^, alors vous n'en avez pas besoin .*)
Boris Dalstein
30

L'expression régulière *représente zéro ou arbitrairement plusieurs. Donc, vous avez dit apt-getde supprimer tout ce qui contient k3suivi de n'importe quel nombre de b, donc tout ce qui contient k3. Si j'essaie votre commande sur mon système, il veut supprimer 58 paquets.

sudo apt-get remove -s k3b*
Package k3b is not installed, so not removed
Package k3b-data is not installed, so not removed
Package k3b-dbg is not installed, so not removed
Package libcanberra-gtk3-0 is not installed, so not removed
Package libcanberra-gtk3-0-dbg is not installed, so not removed
Package libcanberra-gtk3-dev is not installed, so not removed
…
The following packages will be REMOVED:
  appmenu-gtk ardour audacity brasero brasero-cdrkit firefox-globalmenu
  gconf-editor gir1.2-appindicator-0.1 gnome-applets gnome-control-center
…
0 upgraded, 2 newly installed, 58 to remove and 0 not upgraded.
qbi
la source
Pouah! Cela fait trop longtemps que je suis en train de travailler sur ces machines de fenêtres (où * signifie simplement "et rien après")!
Steve Goykovich
14
Le *ne fonctionne comme un joker pour bash comme dans DOS, mais certaines des commandes comme apt-getattendre une expression régulière. Lorsque vous tapez sudo apt-get remove -s k3b*, bash commence par rechercher les fichiers de votre répertoire actuel commençant par k3b. S'il en trouve, il remplacera cet argument par ces noms de fichiers. Sinon, il passera k3b*directement à apt-getqui l'interprétera comme une regex. Si vous ne voulez pas que bash interprète d'abord l'astérisque comme un caractère générique (ce que vous n'avez probablement pas), entourez l'argument par des guillemets simples, comme ceci:sudo apt-get remove -s 'k3b*'
Flimm
3
Donc, la commande prévue aurait été sudo apt-get remove -s 'k3b.*'. Je suis tombé par hasard sur cette réponse et trouve qu'il est vraiment important de savoir. IMHO c'est assez inattendu et je le marquerais plutôt comme un bogue de "comportement inattendu" d'apt-get ... vous attendez normalement un sens "glob" et pas un sens "regexp" s'il n'est pas spécifié. Merci quand même et +1!
Rmano
1
Et pour ceux qui comme moi ne le savaient pas: l' -soption signifie "simulation". Il vous dit de apt-getne pas effectuer l'opération, mais simplement de vous informer de ce qui se passerait sans l' -soption.
Boris Dalstein
Je pense que votre utilisation de guillemets simples pour créer un déplacement ne marche PAS, du moins en marionnette. Et c'est inattendu. Dans le programme 'find', si j'écris find / -iname 'project *', je trouverai tout ce qui commence par projet, pas quelque chose qui contient 'projet' et tout ce qui suit. Comme preuve concernant la marionnette, remarquez comment mes résultats disent «regex», et les résultats le prouvent?
Dennis
9

Utilisez à la sudo apt-get remove ^k3bplace. Lorsque vous installez ou supprimez des paquetages, cela *est souvent dangereux et rarement nécessaire. Si vous utilisez *, vous devriez citer, mais cela ne pas le rendre plus sûr, parce que sa tendance à choisir des paquets beaucoup plus que vous avez l' intention est le résultat de la manière aptet l' apt-getinterpréter et non un effet de l' expansion du chemin .

  • Même les utilisations sécurisées* sont souvent inutiles .
  • Les utilisations dangereuses sont brutales . Supprimer k3b*supprime chaque paquet qui contient k3 n'importe où dans son nom (et chaque paquet qui dépend d'un tel paquet). Ce n'est pas une faute de frappe - contenir k3est suffisant, même sans le b, parce que b*signifie "zéro ou plus de bs".

Lorsque vous exécutez aptou apt-getavec le install, removeou l' purgeaction, chaque argument ultérieur est d' abord 1 interprété comme le nom d'un emballage individuel. S'il existe un package portant exactement ce nom, l'action est effectuée sur celui-ci.

S'il n'y a pas tel paquet, aptet apt-getvérifiera si l'argument contient l' une des communes expression régulière métacaractères 2 . , ?, +,* , |, \[, ^ou$ . Sinon, c'est fait - aucun paquet n'a été trouvé.

Si elle ne contient aucun de ces caractères, il est traité comme une expression régulière et en correspondance avec une partie d'un nom de package. Il ne doit pas nécessairement correspondre au nom complet. Comme d'autres l'ont déjà dit, l' *expression régulière ne signifie pas la même chose que *dans un glob. ?non plus. Dans une expression régulière:

  • *permet à l'élément précédent d'apparaître autant de fois que nécessaire - y compris une seule fois ou pas du tout - au lieu d'une seule fois.
  • ?rend l’élément précédent facultatif - c’est-à-dire qu’il lui permet d’apparaître zéro ou une fois.

apt-get (8) ( man apt-get) dit:

Si aucun paquet ne correspond à l'expression donnée et que celle-ci contient l'un des '.', '?' ou '*' alors il est supposé être une expression régulière POSIX et il est appliqué à tous les noms de packages de la base de données. Toutes les correspondances sont ensuite installées (ou supprimées). Notez que la correspondance est effectuée par sous-chaîne, donc 'lo. *' Correspond à 'how-lo' et à 'lower'. Si cela n'est pas souhaité, ancrez l'expression régulière avec un caractère '^' ou '$' ou créez une expression régulière plus spécifique.

La page de manuel mentionne seulement ., ?et *, mais il est incomplet , comme +, |, [, ^et $sont également suffisantes pour laisser apt-getou aptinterpréter le motif comme une expression régulière. 3

Bien que vous puissiez faire correspondre un nombre quelconque de caractères avec .*- pas seulement - vous n'en* avez besoin que s'il apparaît au milieu de votre expression régulière. Comme le modèle correspond à n'importe quelle sous-chaîne d'un nom de package, il est inutile à la fin (ou au début) du modèle.

La page de manuel mentionne ^et$ . Ceux - ci ( en particulier ^) sont essentielles à l' écriture des motifs sécuritaires et efficaces pour une utilisation avec les install, removeou purgeactions aptou apt-get.

  • ^ancre une expression régulière au début de la chaîne entière. ^k3bsélectionne tous les paquets dont le nom commence par k3b.
  • $ancre une expression régulière à la fin de la chaîne entière. k3b$sélectionnerait tous les paquets dont le nom se termine par k3b.

Par conséquent, vous pouvez utiliser cette commande pour supprimer les packages en toute sécurité:

sudo apt-get remove ^k3b

Enfin, dans le cas spécifique que vous avez mentionné, vous pourriez aussi bien donner les deux noms vous-même:

sudo apt-get remove k3b k3b-data

Alors vous évitez toute cette complexité! (Bien que l'ancrage avec ^soit simple une fois que vous y êtes habitué.) Ou utilisez le développement d'accolade , que votre shell développe dans la commande ci-dessus:

sudo apt-get remove k3b{,-data}

1 Il y a deux exceptions à cela: (a) certaines options (par exemple -f, --purge) sont reconnus, et (b) certains caractères de ponctuation apparaissant à la fin d'un argument qui serait autrement considéré comme un nom de package pour exécuter l'action peut être utilisé pour modifier ce qui est fait (par exemple, sudo apt install ubuntu-desktop^installe la tâche plutôt que le paquet, et quand ^apparaît à la fin).

2 Il existe d'autres métacaractères d'expression régulière. Par exemple, \est pris en charge par tous les dialectes d'expressions régulières et couramment utilisés. ., ?, +, *, |, [, ^, Et $Il se trouve que les métacaractères les développeurs APT ont décidé déclencherait l' interprétation comme une expression régulière (après résolution comme un paquet exact nommé a échoué).

3 Le moyen le plus simple de vérifier cela consiste à simuler l'installation ou la suppression à l'aide d'un tel motif, en utilisant l' -soption décrite ci-dessus. Par exemple, l'exécution de apt -s install ^virtualboxshows qui sudo apt install ^virtualboxaurait pour effet d'essayer d'installer chaque paquet connu du gestionnaire de paquets dont le nom commence par virtualbox. Toutefois, ce comportement peut également être vérifié en examinant le code source . Vérifiez la CacheSetHelper::PackageFromRegExfonction dans cacheset.cc.

Eliah Kagan
la source
1

Vous supprimez plus probablement une bibliothèque contenant k3b et sur laquelle reposent ces programmes.

En bref, vous ne saurez peut-être jamais. Je recommande de ne pas utiliser de caractère générique pour supprimer des éléments et lire des éléments lorsque vous y êtes invité (désolé).

De plus, avec -n, les recherches regex utilisent tous les champs et pas seulement les noms

http://ccrma.stanford.edu/planetccrma/man/man8/apt-cache.8.html

aussi qbi est correct votre regex est imparfait dès le départ

coteyr
la source
Une autre chose, dans des cas comme le vôtre (données k3b et k3b), il suffit de désinstaller apt-get pour k3b. Apt vous informera ensuite si vous avez installé des éléments dont vous n’avez plus besoin et ce que vous devez faire pour les supprimer.
coteyr
Hou la la! Je n'aurais jamais espéré qu'il recherche aussi dans les descriptions! oui, c'est définitivement quelque chose que je ne referai plus jamais! (et je ne manquerai pas de lire les choses la prochaine fois: P)
Steve Goykovich Le
Le lien est brisé, pourriez-vous préciser comment utiliser le -n?
Seanny123
-n signifie que seul le champ de recherche est recherché.
coteyr
Après avoir essayé, l'option -n n'est pas reconnue par apt-get remove, mais par apt-get cache. Il semble qu’en fait, apt-get removene cherche que les noms de paquets, pas les descriptions.
Boris Dalstein