apt-get remove com curinga removido muito mais do que o esperado. porque?

38

Ontem à noite eu estava tentando gravar CDs. Ficando irritado com o k3b e optando por usar o brasero, fui remover o k3b.

Eu digitei:

sudo apt-get remove k3b

Apertei a tecla tab duas vezes e vi que tinha os dados k3b e k3b no meu sistema. Supondo que não precisaria de dados k3b no meu sistema sem o k3b, também queria removê-los e digitei:

sudo apt-get remove k3b*

Infelizmente, apertei Y para confirmar sem olhar. Desinstalou muito mais do que k3be k3b-data. Desinstalou pacotes que não se encaixavam no meu k3b*regex. Por exemplo: transmissione network-manager.

Estou bastante certo de que eu não tinha um espaço entre k3be *mas eu não sei porque senão ele iria remover tudo o que ele fez. Existe algo sobre o apt-get que estou entendendo mal?

Steve Goykovich
fonte

Respostas:

38

O comando que você deseja é sudo apt-get remove '^k3b.*', porque:

  • Você precisa .*combinar qualquer caractere, quantas vezes desejar
  • Você precisa ^coincidir com o início da string
  • Você precisa citar o regex para impedir que o bash interprete *como curinga

(Esta resposta completa e resume as informações anteriores fornecidas por qbi e Flimm)

Boris Dalstein
fonte
5
Isso é seguro e não há problema em usá-lo, mas você não precisa do .*. Você pode apenas usar sudo apt-get remove ^k3b. A presença de ^é suficiente para fazer com que o argumento seja interpretado como uma expressão regular e quando aptou apt-getinterpreta um argumento como uma expressão regular, ele corresponde a qualquer lugar do nome do pacote. É por isso que você precisa ^- ancorar a correspondência no início do nome do pacote. A expressão regular não precisa corresponder ao nome inteiro do pacote, apenas a qualquer parte dele.
Eliah Kagan
11
@EliahKagan Thx para informações adicionais! (e, na verdade, faz sentido que se você precisa ^, então você não precisa .*)
Boris Dalstein
30

A expressão regular *representa zero ou arbitrariamente muitos. Então você disse apt-getpara remover qualquer coisa que contenha k3seguida por qualquer número de b, então basicamente tudo que contém k3. Se eu tentar o seu comando no meu sistema, ele deseja remover 58 pacotes.

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
fonte
ugh! Estou preso trabalhando nessas máquinas danadas do Windows (onde * significa apenas "e qualquer coisa depois") por muito tempo!
Steve Goykovich
14
Ele *funciona como um curinga para o bash, como no DOS, mas alguns comandos apt-getesperam um regex. Quando você digita sudo apt-get remove -s k3b*, o bash primeiro procura por arquivos no diretório atual que começam com k3b. Se encontrar algum, substituirá esse argumento por esses nomes de arquivos. Caso contrário, ele passará k3b*diretamente para apt-get, o que o interpretará como um regex. Se você não quer bash para interpretar o asterisco como um curinga primeiro (que você provavelmente não), coloque o argumento entre aspas simples, como este:sudo apt-get remove -s 'k3b*'
Flimm
3
Portanto, o comando pretendido teria sido sudo apt-get remove -s 'k3b.*'. Apenas encontrei esta resposta e achei realmente importante saber. IMHO isso é bastante inesperado e eu o marcaria como um bug de "comportamento inesperado" do apt-get ... você normalmente espera um significado "glob" e não um "regexp" se não for especificado. Obrigado mesmo assim e +1!
Rmano 10/03/2014
11
E para aqueles como eu que não sabiam: a -sopção significa "simulação". Diz apt-getpara não executar a operação, mas simplesmente para informá-lo do que aconteceria sem a -sopção.
Boris Dalstein
Eu acho que o uso de aspas simples para criar globbing NÃO funciona, pelo menos em fantoches. E isso é inesperado. No programa 'find', se eu escrever find / -iname 'project *', encontrarei tudo o que começa com o projeto, não algo que tenha 'project' nele e qualquer coisa depois dele. Como prova do boneco, observe como meus resultados dizem 'regex' e os resultados provam isso?
Dennis
9

Use em sudo apt-get remove ^k3bvez disso. Quando você instala ou remove pacotes, *geralmente é perigoso e raramente necessário. Se você usar *, deve citá-lo, mas isso não o torna mais seguro, porque a tendência de selecionar muito mais pacotes do que você pretende é o resultado do caminho apte apt-getinterpretá-lo, e não um efeito da expansão do nome do caminho .

  • Mesmo usos seguros de* são muitas vezes desnecessários .
  • Usos inseguros são brutais . A remoção k3b*remove todos os pacotes que contêm k3 qualquer lugar em seu nome (e todos os pacotes que dependem desse pacote). Isso não é um erro de digitação - k3é suficiente, mesmo sem o b, porque b*significa "zero ou mais bs".

Quando você executa aptou apt-getcom o install, removeou purgeação, cada argumento posterior é o primeiro 1 interpretado como o nome de um pacote individual. Se um pacote com esse nome exato existir, a ação será executada para ele.

Se não existe tal pacote, apte apt-getirá verificar se o argumento contém qualquer um dos comuns de expressões regulares metacharacters 2 . , ?, +,* , |, \[, ^, ou$ . Caso contrário, está feito - nenhum pacote foi encontrado.

Se ele não contém nenhum desses personagens, então ele é tratado como uma expressão regular e comparado com qualquer parte de qualquer nome do pacote. Não precisa corresponder ao nome inteiro. Como outros já disseram, *em uma expressão regular não significa a mesma coisa que *em uma glob. ?também não. Em uma expressão regular:

  • *permite que o item anterior apareça inúmeras vezes - incluindo apenas uma vez ou não - em vez de exatamente uma vez.
  • ?torna o item anterior opcional - ou seja, permite que ele apareça zero ou uma vez.

O apt-get (8) ( man apt-get) diz:

Se nenhum pacote corresponder à expressão fornecida e a expressão contiver um de '.', '?' ou '*', assume-se que seja uma expressão regular POSIX e é aplicada a todos os nomes de pacotes no banco de dados. Todas as correspondências são instaladas (ou removidas). Observe que a correspondência é feita por substring, então 'lo. *' Corresponde a 'how-lo' e 'lower'. Se isso não for desejado, ancore a expressão regular com um caractere '^' ou '$' ou crie uma expressão regular mais específica.

A manpage apenas menciona ., ?e *, mas é incompleta , como +, |, [, ^, e $também são suficientes para deixar apt-getou aptinterpretar o padrão como uma expressão regular. 3

Embora você possa combinar qualquer número de caracteres com .*- e não apenas -, você *só precisa disso se ele aparecer no meio da sua expressão regular. Como o padrão é comparado com qualquer substring de um nome de pacote, não faz sentido o final (ou o começo) do padrão.

A página de manual menciona ^e$ . Estes (especialmente ^) são a chave para escrever padrões seguras e eficientes para uso com os install, removeou purgeações em aptou apt-get.

  • ^ancora uma expressão regular no início de toda a cadeia. ^k3bseleciona todos os pacotes cujos nomes começam com k3b.
  • $ancora uma expressão regular no final de toda a cadeia. k3b$selecionaria todos os pacotes cujos nomes terminam com k3b.

Portanto, você pode usar este comando para remover com segurança os pacotes:

sudo apt-get remove ^k3b

Finalmente, no caso específico que você mencionou, você também pode apenas passar os dois nomes:

sudo apt-get remove k3b k3b-data

Então você evita toda essa complexidade! (Embora a ancoragem com ^seja simples quando você estiver acostumado a isso.) Ou use expansão de chaves , que seu shell expande no comando acima:

sudo apt-get remove k3b{,-data}

1 Há duas excepções a esta: (a) algumas opções (por exemplo, -f, --purge) são reconhecidos, e (b) alguns caracteres de pontuação que aparecem no final de um argumento que seria tomado como um nome de pacote para executar a ação pode ser usado para alterar o que é feito (por exemplo, sudo apt install ubuntu-desktop^instala a tarefa em vez do pacote e quando ^aparece no final).

2 Existem outros metacaracteres de expressão regular. Por exemplo, \é suportado por todos os dialetos de expressões regulares e comumente usado. ., ?, +, *, |, [, ^, E $só acontecerá a ser os metacaracteres os desenvolvedores APT decidiram provocaria interpretação como uma expressão regular (após a resolução como um pacote exato nomeado falhou).

3 A maneira mais fácil de verificar isso é simular a instalação ou remoção com esse padrão, usando a -sopção descrita acima. Por exemplo, a execução de apt -s install ^virtualboxprogramas que sudo apt install ^virtualboxteriam o efeito de tentar instalar todos os pacotes que o gerenciador de pacotes conhece sobre cujo nome começa virtualbox. No entanto, esse comportamento também pode ser verificado examinando o código-fonte . Verifique a CacheSetHelper::PackageFromRegExfunção em cacheset.cc.

Eliah Kagan
fonte
1

É mais provável que você remova uma lib que continha o k3b da qual esses programas dependiam.

Em resumo, você pode nunca saber. Eu recomendo não usar um curinga para remover e ler as coisas quando solicitado (desculpe).

Também sem as pesquisas -n regex, use todos os campos e não apenas nomes

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

também qbi está correto seu regex é falho desde o início

coteyr
fonte
Outra coisa, em casos como o seu (dados do k3b e k3b), basta apt-get uninstall k3b. O Apt informará se você possui itens instalados que não são mais necessários e o que você precisa fazer para removê-los.
coteyr
Uau! Eu nunca esperaria que ele pesquisasse também nas descrições! Sim, isso é definitivamente algo que nunca mais farei! (e eu vou ter certeza de ler as coisas da próxima vez: P)
Steve Goykovich 02/11/12
O link está quebrado, você se importaria de esclarecer como usar o -n?
precisa saber é o seguinte
-n significa apenas pesquisar no campo de nomes.
coteyr
Depois de tentar, a opção -n não é reconhecida por apt-get remove, apenas por apt-get cache. Parece que, na verdade, apt-get removeapenas procura nomes de pacotes, não descrições.
Boris Dalstein