List all commands of a specific Debian package

Use dpkg -L pkgname and pipe it to a grep command searching for bin/ and games/:

$ dpkg -L bash | grep -E '(bin|games)/'
/bin/bash
/usr/bin/bashbug
/usr/bin/clear_console
/bin/rbash

If you want to check for all binaries regardless if they are in your $PATH try this bash function:

find_binaries (){
    dpkg -L "$@" | while read; do
        [ -f "$REPLY" -a -x "$REPLY" ] && echo "$REPLY"
    done
}

Invoke like so:

$ find_binaries postfix
...SNIP...
/usr/lib/postfix/postfix-files
/usr/lib/postfix/pipe
/usr/lib/postfix/proxymap
/usr/lib/postfix/local
/usr/lib/postfix/discard
...SNIP...

1. Use a tool designed for the job.

The easiest and probably the most robust way is to install dlocate:

sudo apt-get install dlocate

You can then run

dlocate -lsbin package-name

As explained in man dlocate:

-lsbin List full path/filenames of executable files (if any) in package

2. Parse the package database

This is a similar approach to @Winny's but simplified

apt-file -F list package | cut -d ' ' -f 2 | 
    while read file; do [[ -x $file && -f $file ]] && echo "$file"; done

If you don't have apt-file installed, you can install and set it up with these commands:

sudo apt-get install apt-file
sudo apt-file update

The command above uses apt-file to list a package's contents and then bash's tests -f (is this a file?) and -x (is it executable?) and prints the file's name if both tests are passed.

Note that while something like the command below will get you most executables:

apt-file -L list package | grep -Ew 'bin|sbin'

it will not find all because you also get executables in places like /opt or even /lib (various udev tools for example). So, while using the -w to match whole words increases your chances of identifying the files correctly, parsing the path is not a good approach and you should use one of the methods above instead.


If you have dlocate installed, there's an easy way to list all the commands in an installed package:

dlocate -lsbin PACKAGE-NAME

With just dpkg, you can list the files in the standard PATH directories (they're almost all executable programs, with very few exceptions):

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

The exceptions are a couple directories — as of Debian wheezy, just two: /usr/bin/mh and /usr/bin/nu-mh.

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

apt-file -F list PACKAGE-NAME… | sed -n 's!^\(/s\?bin\|/usr/s\?bin\|/usr/games\)/!!p' | sort -u

While there are executable files in other directories, they are not meant to be executed directly, which makes them irrelevant here.

These methods all miss a set of programs: those that are provided through the alternatives mechanism. 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.