Come faccio ad elencare i comandi forniti da un pacchetto? [duplicare]

12

Sono curioso di sapere quali comandi un determinato pacchetto fornisce al mio sistema. Per comando, intendo un eseguibile in-path che posso eseguire dalla riga di comando ( ls , grep , sed , ecc.)

Sono non cercando di elaborare il pacchetto dal comando, che può essere eseguito con:

dpkg -S 'which command'

Voglio il contrario, una lista di comandi da un pacchetto.

    
posta Oli 19.03.2014 - 11:35
fonte

4 risposte

8

Il seguente piccolo ciclo gestirà questo con i pacchetti installati .

$ for f in $(dpkg -L login); do [[ $(type -P "${f##*/}") == "$f" ]] && echo ${f##*/}; done
nologin
lastlog
newgrp
faillog
su
login
sg

Come funziona:

  • dpkg -L package genera un elenco di tutti i file in un pacchetto da noi iterato.
  • Spogliamo il nome della directory con un po 'di bashismo: ${f##*/} e
  • Usando il bash-builtin type -P command vediamo se quel comando è nel percorso e che il suo percorso è uguale al file con cui abbiamo iniziato.
  • Finiamo con il pompaggio del comando abbreviato.
  • [[ condition ]] && command è solo una scorciatoia di bash per un'istruzione if..then.

È importante notare che non tutti i pacchetti contengono i comandi che ci si aspetterebbe che facciano. Apache è suddiviso su più pacchetti (con -common e -bin subpackages) e il comando vlc non è nel pacchetto vlc , è in vlc-nox . Ci sono molti esempi del genere.

Può essere adattato per l'idea di Gilles , eseguendo una corrispondenza di stringa invece di controllare effettivamente, ma mantenendo tutto in uno processo bash (e ancora utilizzando il percorso intero ).

for f in $(dpkg -L login); do [[ $f =~ ^${PATH//:/|} ]] && echo ${f##*/}; done

La principale differenza qui è [[$f =~ ^${PATH//:/|} ]] . Questa è una ricerca regolare in-Bash. La parte ${PATH//:/|} sta prendendo i contenuti di $ PATH e li sta violando in una piccola regex sporca. La condizione dovrebbe verificare che la stringa inizi con una parte del percorso.

    
risposta data Oli 19.03.2014 - 11:35
fonte
3

Elenca i file nel pacchetto che si trovano in una directory nel PERCORSO. Devi solo considerare il PATH predefinito, non le personalizzazioni dell'utente, poiché i pacchetti utilizzano solo directory standard.

dpkg -L PACKAGE-NAME… | sed -n 's!^\(/s\?bin\|/usr/s\?bin\|/usr/games\)/!!p' | sort

Rimuovi s\? parti se vuoi che i programmi siano pensati per gli utenti normali senza sudo .

Se il pacchetto non è installato, sostituisci dpkg -L con apt-file -F list .

Mancano alcuni programmi perché vengono forniti tramite alternative . Ad esempio, per il pacchetto ftp , vengono forniti solo netkit-ftp e pftp , ma questo pacchetto fornisce effettivamente il comando ftp , perché /usr/bin/ftp è un collegamento simbolico a /etc/alternatives/ftp che è un collegamento simbolico a una delle implementazioni ftp sul sistema, potenzialmente /usr/bin/netkit-ftp . Il seguente comando (che non è un esempio di buona programmazione, ma solo un grande liner) elenca i comandi forniti da un pacchetto tramite il meccanismo alternativo, come attualmente configurato.

perl -lwe 'foreach ('dpkg -L @ARGV') {chomp; ++$p{$_}} foreach (</bin/* /sbin/* /usr/bin/* /usr/sbin/*>) {$e = readlink; next unless defined $e and $e =~ m!^/etc/alternatives/!; $t = readlink $e; print if $p{$t}}' PACKAGE_NAME…

Se vuoi elencare i comandi che potrebbero essere forniti tramite un'alternativa che è attualmente configurata per puntare a un altro pacchetto, devi analizzare i file in /var/lib/dpkg/alternatives .

I link simbolici e i file di configurazione che implementano i meccanismi alternativi non sono registrati nei pacchetti ma registrati automaticamente in postinst , il che rende difficile (e di fatto tecnicamente impossibile se lo script di installazione di un pacchetto non segue le convenzioni) per interrogare il alternative fornite da un pacchetto disinstallato.

    
risposta data Gilles 19.03.2014 - 12:59
fonte
1

La mia altra risposta è abbastanza certa, ma funziona solo per i pacchetti installati. Ecco una crepa a una versione che funziona con pacchetti non ancora installati (ma quelli che sono disponibili solo nei repository principali)

export PACKAGE="login"; source /etc/lsb-release; source <(dpkg-architecture); for f in $(wget -qO- "http://packages.ubuntu.com/$DISTRIB_CODENAME/$DEB_BUILD_ARCH/$PACKAGE/filelist" | sed -n '1,/<pre>/d;/<\/pre>/,$d;p'); do [[ $f =~ ^${PATH//:/|} ]] && echo ${f##*/}; done

È orribilmente più complicato, quindi scriverò una versione suddivisa:

export PACKAGE="login";
source /etc/lsb-release;
source <(dpkg-architecture);

URL="http://packages.ubuntu.com/$DISTRIB_CODENAME/$DEB_BUILD_ARCH/$PACKAGE/filelist"

# We grab the packages.ubuntu.com version of the file list (and strip it with sed)
for f in $(wget -qO- "$URL" | sed -n '1,/<pre>/d;/<\/pre>/,$d;p'); do

    # We then compare every file provided in the package with every path stub
    [[ $f =~ ^${PATH//:/|} ]] && echo ${f##*/};
done
    
risposta data Oli 19.03.2014 - 13:08
fonte
0

Un metodo più semplice è solo interrogare il web:

release=$(lsb_release -sc)
arch=$(uname -m)
package=$@

for i in $package; do
   printf "List of files in $i package"
   curl http://packages.ubuntu.com/$release/$arch/$i/filelist 2>/dev/null | grep -oP '/[\w\d/.]+$
done

Questo ha il vantaggio che avresti solo bisogno di curl e sed (il sistema di Ubuntu non li ha) e puoi cambiarlo con wget facilmente se necessario. Interroga molti pacchetti con un singolo comando che è un vantaggio.

Qualsiasi equivalente con altri linguaggi di programmazione + parser html dovrebbe funzionare meglio e meno probabilità di interruzione se qualcosa cambia nella lista dei pacchetti.

Cambiando l'host puoi anche interrogare il database Debian.

    
risposta data Braiam 19.03.2014 - 15:46
fonte

Leggi altre domande sui tag