Linux/Unix: Finding all commands on the system
đ Wiki page | đ Last updated: Dec 23, 2022I recently needed a list of all available commands on the system. Here are a few ways you can achieve that.
Since the PATH environment variable contains a list of directories with executable files, we could start by iterating over files in those directories, filtering them, and caching the result, but your shell is typically already doing all that job (in a pretty efficient way).
compgen
If you're using bash, compgen
is a handy built-in command, which can provide us with the data that is used for the auto-completion feature.
We can get list of all command names by providing the -c
switch:
compgen -c
And we can easily sort the result:
compgen -c | sort
zsh
On zsh
that doesn't work out of the box, but you can install the completion system with compinstall
. You can enable it with something like:
autoload -Uz bashcompinit
bashcompinit
This will provide you with a compgen
command which works similarly to the bash version.
Alternatives
If your directories in $PATH are relatively clean (containing no extra files), the solution could be as simple as this:
IFS=:; ls $PATH | sort -u
Note: Since $PATH uses a double colon as a directory separator, we can't give it directly to ls
. Instead of manipulating the string with something like sed
, I'm using IFS
variable to change the standard input field separator (more info: Linux/Unix: Understanding IFS (Input Field Separators)).
In practice, directories in $PATH aren't always super clean, so instead of ls
, we can use find
to filter only executable files:
IFS=:; find $PATH -type f -executable -maxdepth 1 -print | sort -u
Note: if you're using non-GNU version of find, you'll have to use something like -perm +111
instead of -executable
.
And since we're only interested in commands, and find
doesn't support returning only the last part of the path, we need to do that ourselves:
IFS=:; find $PATH -type f -executable -maxdepth 1 -print | sed 's|.*/||' | sort -u
stest
There's a nice util called stest
(part of "suckless" tools) which we can use here instead of find
and sed
:
IFS=:; stest -flx $PATH | sort -u
Installation
stest
is usually a part of the dmenu
or suckless-tools
package, depending on the distro:
# deb-based
apt install suckless-tools
# rpm-based
dnf install dmenu
# Arch
pacman -S dmenu
Ask me anything / Suggestions
If you find this site useful in any way, please consider supporting it.