Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

This question already has an answer here:

I'm curious what commands a certain package provides my system with. By command, I mean an in-path executable that I can run from the command line (ls, grep, sed, etc).

I'm not trying to work out the package from the command, which can be done with:

dpkg -S `which command`

I want the opposite, a list of commands from a package.

share|improve this question

marked as duplicate by terdon, Jorge Castro, Eliah Kagan, BuZZ-dEE, Aditya Mar 20 at 19:51

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

    
askubuntu.com/questions/176679/… This seems like related question. –  devav2 Mar 19 at 11:23
2  
Perhaps this could be merged with How can I know what programs does some apt-get package contents?? It has pretty much the same information, only the answers don't limit themselves to the PATH. Merging might be a good idea to have the PATH approach as well. –  terdon Mar 19 at 15:55

4 Answers 4

The following little loop will handle this with installed packages.

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

How it works:

  • dpkg -L package generates a list of all the files in a package which we iterate through.
  • We strip off the directory name with a little bashism: ${f##*/} and
  • Using the bash-builtin type -P command we see if that command is both in the path and that its path equals the file we started with.
  • We finish by pumping out the shortened command.
  • [[ condition ]] && command is just a bash shorthand for an if..then statement.

It's important to note that not all packages contain the commands you would expect them to. Apache is split out over multiple packages (with -common and -bin subpackages) and the vlc command isn't in the vlc package, it's in vlc-nox. There are many examples like that.


This can be adapted per Gilles's idea, doing a string match instead of actually checking, but keeping it all in one bash process (and still using the whole path).

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

The major difference here is the [[$f =~ ^${PATH//:/|} ]]. That's an in-Bash regex search. The ${PATH//:/|} part is taking the contents of $PATH and is hacking them into a dirty little regex. The condition should check the string begins with part of the path.

share|improve this answer
    
I tried for f in $(dpkg -L apache2); do [[ $(type -P "${f##*/}") == "$f" ]] && echo ${f##*/}; done NO results –  user259474 Mar 19 at 10:42
1  
@user259474 This is expected. The apache2 package doesn't contain much, it's more a of a meta package. The commands are in -common and -bin subpackages. –  Oli Mar 19 at 10:45
1  
That's a bizarre way of doing it: more complex and less reliable than looking for /bin and friends textually. –  Gilles Mar 19 at 12:00

List the files in the package which are in a directory in the PATH. You only have to consider the default PATH, not any user customizations, since packages only use standard directories.

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

Remove the s\? parts if you only want the programs intended for ordinary users without sudo.

If the package isn't installed, replace dpkg -L by apt-file -F list.

This misses a few programs because they are provided via alternatives. For example, for the ftp package, only netkit-ftp and pftp are provided, but this package actually provides the ftp command, because /usr/bin/ftp is a symbolic link to /etc/alternatives/ftp which is a symbolic link to one of the ftp implementations on the system, potentially /usr/bin/netkit-ftp. The following command (which isn't an example of good programming, just a big one-liner) lists the commands provided by a package via the alternatives mechanism, as currently configured.

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…

If you want to list the commands that could be provided via an alternative which is currently configured to point to a different package, you need to parse the files in /var/lib/dpkg/alternatives.

Symbolic links and configuration files that implement the alternatives mechanisms are not registered in packages but registered automatically in postinst, which makes it difficult (and in fact technically impossible if a package's installation script doesn't follow conventions) to query the alternatives provided by an uninstalled package.

share|improve this answer
    
I'm a bit wary of apt-file mostly because it entails downloading a large amount of data before you can start using it. For a lot of packages, some sort of spin around apt-get download would be faster. –  Oli Mar 19 at 12:58
1  
@Oli I wish that apt-file was part of the default installation. The amount of data is only a little more than one non-incremental round of apt-get update, and it's something you need to do once per release. –  Gilles Mar 19 at 13:09
    
lightdm appears to the only path in $PATH that buck's the trend here. You're not catching /usr/lib/lightdm/ which contains executables for some ungodly reason. Approach this from the other side... Apart from perhaps taking a little longer, is checking the active path going to be erroneous? –  Oli Mar 19 at 13:24
    
Just noticed you rolled this back. Without -F, apt-file list is very baggy (and doesn't answer the question at all). Try it with login if you want to see what I'm talking about. –  Oli Mar 19 at 16:25
1  
dlocate works wonderfully for installed packages, even gets the ones in /lib though it doesn't deal with alternatives. –  terdon Mar 20 at 18:19

My other answer is fairly certain but only works for installed packages. Here's a crack at a version that works for packages not yet installed (but ones that are only available in the main repositories)

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

It's horrifically more complicated so I'll write a broken down version:

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
share|improve this answer
    
Unless you have very limited bandwidth and are installing from CD, it's simpler to use apt-file. And again use hard-coded directories, not the user's $PATH. –  Gilles Mar 19 at 13:11

An easier method is just querying the 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

This has the advantage that you would only need curl and sed (what Ubuntu system doesn't have them) and you can change it with wget easily if necessary. It queries several packages with a single command which is a plus.


Any equivalent with other programing language + html parser should work better and less likely to break if something change in the package list.

Changing the host you can also query Debian database.

share|improve this answer

protected by Community Mar 20 at 13:10

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.