A few shells have builtin support for that.
zsh
Many of the zsh
shell's introspection builtin commands take a -m
argument to do pattern m
atching. That's the case of whence
(copied and extended from ksh) used to identify commands and the variants provided for convenient for other shell users (which
same whence -c
for csh users, type
(standard), same as whence -v
for SysV shell users) and the standard hash
builtin to manipulate internal hash tables including that of paths of commands.
whence -m '*mod*'
type -m '*mod*'
which -m '*mod*'
hash -m '*mod*'
The first 3 also look in builtins, functions, keyword, aliases; add -p
to limit to commands in $PATH
like for hash
.
Or you can look for matching executable files in $PATH
(mapped to the $path
array) manually with¹:
print -rC1 -- $^path/*mod*(DN-*)
In addition to some builtin commands, for introspection (and for helping with completion), zsh exposes some of its internal state and cached data in some special variables. For instance the hash table of commands and their path is exposed in the $commands
special associative array, so you can look in its keys with for instance:
print -rC1 -- ${(kM)commands:#*mod*}
Where the pattern matching is done using the ${(M)array:#pattern}
operator.
There, you can also configure completion system to attempt wildcard matching in addition to normal completion. For instance, at a minimum, with:
zstyle ':completion:*' completer _complete _match
autoload -Uz compinit
compinit
In your ~/.zshrc
, typing
$ *mod*<Tab>
Will show you a list of possible commands matching that patterns. While:
$ man -s1,8 *mod*<Tab>
Completing manual page
check-module mk_modmap
chmod modinfo
combine_lang_model modprobe
depmod perlmod
dh_gtkmodules perlmodinstall
[...]
Will show you a list of pages in section 1 (user commands) and 8 (system management commands) of the manual that contain mod
.
When starting zsh
for the first time, you should be shown a newuser
menu to tune all this. The above can be found in:
(1) Continue to the main menu.
[...]
(2) Configure the new completion system. (Recommended.)
[...]
(2) Run the configuration tool (compinstall)
[...]
1. Completers: choose completion behaviour for tasks such as
approximation, spell-checking, expansion.
[...]
m. Set completers that modify the behaviour of the four main ones above.
[...]
1. _ignored: Use patterns that were previously ignored if no matches so far.
2. _list: Only list matches until the second time you hit TAB.
3. _oldlist: Keep matches generated by special completion functions.
4. (*) _match: If completion fails, retry with pattern matching.
5. _prefix: If completion fails, retry ignoring the part after the cursor.
And select 4 above. But I would strongly recommend going through all the menus as there are many more goodies in there.
bash
In the bash
shell, you can use:
compgen -cX '!*mod*'
Same as:
compgen -A command -X '!*mod*'
compgen -c
/ compgen -A command
give a list of known commands (including keywords, aliases, builtins and functions), -X
is to exclude those matching a pattern, but with that pattern starting with !
, that's changed from exclusion to inclusion.
rc and derivatives
In rc
, where the $path
list is tied to the $PATH
environment variable like in csh or zsh,
ls -d -- $path/*mod* >[2] /dev/null
Note that rc
doesn't have the equivalent of zsh
's D
or -*
glob qualifiers, so that list is not restricted to files that are executable and doesn't include hidden files.
rc
shares a misfeature with the Bourne shell and most of its derivatives, that non-matching glob patterns are left as-is, so if there's no match in a given directory, we'd get a literal /that/dir/*mod*
. We work around that by passing the list to ls
which complains about those non-existing files with *
in their name but discard those errors with >[2] /dev/null
(same as the 2> /dev/null
of Bourne-like shells or fish
)
fish
Similar to rc
, with the same caveat regarding non-executable, but with hidden file support added by prefixing {.,}
to the pattern:
printf '%s\n' $PATH/{,.}*mod*
POSIX sh
In POSIX sh, you could define a function such as:
find_commands() (
pattern=$1
IFS=:; set -o noglob
set -- $PATH''
IFS=; set +o noglob
for dir do
for file in "${dir:+$dir/}"$pattern "${dir:+$dir/}".$pattern; do
if [ -f "$file" ] && [ -x "$file" ]; then
printf '%s\n' "$file"
fi
done
done
)
Used as:
find_command '*mod*'
¹ Note that it doesn't work properly if there are empty $PATH
components as in PATH=/bin/:/usr/bin:
where the last empty component means looking in the current working directory. That could be worked around by using ${^path/#%/.}
to replace those empty strings with .
, but in any case, having empty $PATH
components (or $PATH
components being relative paths in general) is very bad practice from a security and reliability standpoint and shouldn't be done. Same applies to solutions for other shells given below that manually look in $PATH
/$path
directories.
apropos 'mod'
orman -k 'mod'
? – Z0OM May 26 '23 at 20:10apropos -w '*mod*' | cut -d' ' -f1 | grep 'mod'
orapropos -w '*mod*' | cut -d'(' -f1 | grep 'mod'
orapropos -w '**' | cut -d'(' -f1 | grep 'mod'
– Z0OM May 26 '23 at 20:21man -k '' | cut -d'(' -f1 | grep 'mod'
| Is that what you are looking for, the examples withapropos
andman
? Let me know and I'll post it as an answer. – Z0OM May 26 '23 at 20:32apropos
– Dev Anand Sadasivam May 26 '23 at 20:38ls
orlsmod
, so what's the significance of that example to this question? – muru May 26 '23 at 21:04mod
doesn't suggest completions such asmodinfo
andmodprobe
then it's likely because these commands are in/usr/sbin
, and/usr/sbin
is not in your user'sPATH
– steeldriver May 26 '23 at 23:23