Erro com parênteses no código

Pessoal, eu tenho esse trecho de código que lista os aplicativos .deb instalados em uma máquina com Linux e guarda na vvariável deb

deb = os.popen(“comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n ‘s/^Package: //p’ | sort -u)”).read( ).strip( ).split( )

o problema é que quando eu tento usar essa lista no resto do código aparece essa mensagem:

/bin/sh: 1: Syntax error: “(” unexpected

Onde diz que acontece um erro de sintaxe por haver um “(” no trecho de código.

Tentei colocar “” antes dos parênteses e fica assim:

/bin/sh: 1: cannot open (apt-mark: No such file
sort: invalid option – ‘)’
Try ‘sort --help’ for more information.
/bin/sh: 1: cannot open (gzip: No such file
[]
SE DESEJA DESINSTALAR MAIS DE UM APLICATIVO, DIGITE
CADA NÚMERO CORRESPONDENTE SEPARADO APENAS POR ESPAÇO

0 - VOLTAR

Dessa outra forma:

from subprocess import getoutput

deb = getoutput(“comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n ‘s/^Package: //p’ | sort -u)”).strip( ).split( )

Com “” antes dos parênteses e a saída fica assim:

[’/bin/sh:’, ‘1:’, ‘cannot’, ‘open’, ‘(apt-mark:’, ‘No’, ‘such’, ‘file’, ‘sort:’, ‘invalid’, ‘option’, ‘–’, “’)’”, ‘Try’, “'sort”, “–help’”, ‘for’, ‘more’, ‘information.’, ‘/bin/sh:’, ‘1:’, ‘cannot’, ‘open’, ‘(gzip:’, ‘No’, ‘such’, ‘file’]
SE DESEJA DESINSTALAR MAIS DE UM APLICATIVO, DIGITE
CADA NÚMERO CORRESPONDENTE SEPARADO APENAS POR ESPAÇO

1 - /bin/sh:
2 - 1:
3 - cannot
4 - open
5 - (apt-mark:
6 - No
7 - such
8 - file
9 - sort:
10 - invalid
11 - option
12 - –
13 - ‘)’
14 - Try
15 - ‘sort
16 - --help’
17 - for
18 - more
19 - information.
20 - /bin/sh:
21 - 1:
22 - cannot
23 - open
24 - (gzip:
25 - No
26 - such
27 - file
0 - VOLTAR

Como eu consigo resolver isso?

2 curtidas

Não vi direito

Mas acho que antes dos parentes tem que ter o $

<$(apt

<$(gzip

1 curtida

Bom, no shell está funcionando do mesmo jeito que está aí. O problama é no Python.

@Deleterium
@Capezotte

Você não pode chamar assim, use:

deb = os.popen("bash -c 'comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n \"s/^Package: //p\" | sort -u)' ")

Evite usar .read( ).strip( ).split( ) em uma linha só

Esse bash -c usa o bash pra rodar a linha de comando, note que eu mudei as aspas do sed para aspas duplas e escapei com \ isso é necessário por que nessas condições o bash -c funciona melhor com aspas simples por causa do <(

3 curtidas

Entendo. Eu coloco tudo em uma linha pra não ficar muito maior do que já esta o código, senão vai ter que encher de variável o programa. kkkkkkkkkk

Fiz assim (na teimosia):

deb = os.popen("bash -c 'comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n \"s/^Package: //p\" | sort -u)' ").read( ).strip( ).split( )

e resultou isso:

[]
SE DESEJA DESINSTALAR MAIS DE UM APLICATIVO, DIGITE 
CADA NÚMERO CORRESPONDENTE SEPARADO APENAS POR ESPAÇO

0 - VOLTAR
>

Deu a mesma saída dessa outra forma que encontrei (na teimosia):

deb = getoutput(f'/bin/bash -c "cd {os.getcwd()};comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n \'s/^Package: //p\' | sort -u)"').strip( ).split( )

Posso estar errado na minha conclusão. Mas pra contextualizar é o seguinte: estou tentando criar um aplicativo que ajude usuários de distros Debian-like a personalizar o sistema sem ter que usar o shell e que fique centralizado a maior parte dessas tarefas em um só aplicativo.
Então instalei em máquinas virtuais algumas distros pra poder fazer testes e a que eu estou testando agora é o Elementary OS. Nele, eu consegui listar os aplicativos flatpak e snap que estão instalados no sistema (esse é o motivo de tantos posts com perguntas do tipo como faz pra listar isso ou aquilo outro).
Eu usei esse comando no shell, mas eu creio que foi no meu sistema de uso (Ubuntu 20.04) e funcionou e achei que foi no Elementary OS que esta em uma máquina virtual.
Agora há pouco, eu rodei esse comando:

comm -23 <(apt-mark showmanual | sort -u) <(gzip -dc /var/log/installer/initial-status.gz | sed -n 's/^Package: //p' | sort -u)

e não me mostra nada na saída, enquanto que no Ubuntu mostra tudo como deveria funcionar: a lista com os aplicativos .deb instalados no sistema. A não ser que os aplicativos .deb estejam em um diretório diferente das outras distros. Bom, eu não sei. São só suposições.

Como disse no início: eu posso estar errado, mas eu acho que o Elementary OS não tem aplicativos .deb instalados nele. Me corrijam se eu estiver errado, por favor. É a primeira vez que tento mexer nessa distro.
Essa distro me deixou bugado.

Ah! Eu consegui esse comando com o Dio aqui no fórum.

1 curtida

Isso é bem mais fácil que parece, eu vou quebrar o protocolo e explicar antes como fazer:

  1. Primeiro o comando pra listar os pacotes instalados
dpkg -l

Ele produz uma saída assim:

Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Nome                                 Versão                            Arquitectura Descrição
+++-====================================-=================================-============-===============================================================================
rc  accountsservice                      0.6.55-0ubuntu12~20.04.1          amd64        query and manipulate user account information
ii  adduser                              3.118ubuntu2                      all          add and remove users and groups
  1. Retirando o lixo

Como você quer a lista de pacotes é necessário remover as 5 primeiras linhas e exibir a partir da 6ª, o comando tail -n +6 faz exatamente isso, agora é só passar a saída do dpkg -l usando |

dpkg -l | tail -n +6

Mas ainda sim vai ter um monte de informações a mais

  1. Filtrando a lista

Pra isso você pode usar o cut -d" " -f3 faz isso, é a mesma lógica que o @Capezotte explicou, então vou pular a explicação:

dpkg -l | tail -n +6 | cut -d" " -f3

E pronto, isso lista todos os pacotes .deb instalados no sistema, mas alguns pacotes listam a arquitetura, opcionalmente você pode filtrar com:

dpkg -l | tail -n +6 | cut -d" " -f3 | cut -d: -f1

Assim você tem uma lista pura, aí é só traduzir pro bash -c

  1. O script .py
import os 

deb = os.popen("bash -c 'dpkg -l | cut -d\" \" -f3 | tail -n+6' | cut -d: -f1").read().strip().split()
1 curtida

Embora eles tenham dado preferência a flatpaks eles tem sim debs instalados

É que algumas distros parecem não ter mais esse arquivos, os pacotes instalados pelo usuário se misturam com os do sistema

1 curtida

Vivendo e aprendendo.
Valeu @Natanael.755 .

Mas ainda assim eu achei essa distro estranha.

Eu consegui um comando que “bateu na trave” e só tive que tratar ele no Python pra fazer o que eu preciso.
Ficou assim:

import os

inst = os.popen("cat /var/log/apt/history.log | awk '{if ($3==\"install\" ) {print substr($0,index($0,$4))}}'").read( ).strip( ).split( )
excpt = ['--upgrade', 'update', '--no-install-recommends']
deb = list(set([x for x in inst if (len(x) > 2) and (not x in excpt)]))

Pelo menos, dá pra listar somente os aplicativos instalados pelo usuario. Dessa forma o resto do programa vai sair.
Mas, de qualquer forma, valeu pela ajuda e paciência, pessoal.

Pela minha experiência de programador descobri algo interessante. Diversas vezes que estava complicado demais era porque eu estava tentando do jeito errado. Depois de algum tempo descobria que tinha um jeito mais fácil de resolver.

– edit
O Gentoo tem um gerenciador de pacotes em python. Resolvi dar uma olhada e meu palpite é que eles tiveram problemas parecidos, pois malandramente eles criam arquivos .sh com scripts em bash, e nos arquivos em python não tem comandos em sh. Parece que eles apenas chamam as funções de apoio que estão nos arquivos sh. (não programo em python)