-23

Which command could I use list all commands that start with the letter g? Let's assume I can't use bash completion, and that a script must be written.

Kusalananda
  • 333,661
Liones
  • 17
  • 2
    Welcome new user, some question cause you get negative reputation, before any ask, read the following manual to avoid nagative reputation: http://unix.stackexchange.com/help/asking – PersianGulf Sep 27 '14 at 20:26
  • 1
    Also for avoiding any negative reputation for any answer, read the following link: http://unix.stackexchange.com/help/answering – PersianGulf Sep 27 '14 at 20:27

2 Answers2

1

You basically need to go through all directories listed in PATH and run a find to search for the pattern, in this case, binaries starting with the letter 'g'. Just run:

for i in $(echo $PATH | tr ":" "\n")
do
  find ${i} -iname "g*" 2> /dev/null
done

It's important to mention that some directories might not have one single file matching the regex, so you must discard the error output with 2> /dev/null.

This approach can be useful for many other situations, like searching for a static or dynamic library for example.

  • The echo $PATH bit would not work if you would need to preserve whitespace in any of the path elements, or avoid globbing. It may under some circumstances also interpret backslashes specially. The find command would additionally invoke splitting and globbing (again) on $i, and it would return any name starting with g, executable or not, anywhere below the given directory (these may not be "commands"). – Kusalananda Dec 11 '19 at 07:30
0

There is a single simple command you could use to do this in bash, but it probably violates the requirement of "not using bash completion". I have included this at the end of this answer nonetheless. Instead I'll be using a couple of loops to solve this.

Assuming you'd want to find all executable external commands starting with the letter g in any of the directories listed in your $PATH:

#!/bin/sh

IFS=:; set -f; set -- $PATH; set +f
for dirpath do
    for pathname in "$dirpath"/g*; do
        if [ -x "$pathname" ]; then
            printf 'Executable: %s (%s)\n' "${pathname##*/}" "$pathname"
        fi
    done
done

This first sets the positional parameters to the list of directories held in your PATH variable. It does this by setting IFS to :. This means that when we use $PATH unquoted, its value will be split on the :-characters in the string. To use the variable unquoted safely, we also use set -f to turn off globbing temporarily, just in case any part of the string can be interpreted as a filename globbing pattern. We enabled globbing again with set +f because we need it later.

Once we have set the positional parameters to the list of directory paths, we iterate over these. In each iteration, we get the pathnames of any files that start with the letter g in that directory and test each one to see whether it 1) exists, and 2) is executable (the -x test does both of these things). If it is executable, we output its name and its full pathname.

Note that this is restricting the question to only cover external executable commands in the current $PATH. It will not find aliases or shell functions. Utilities that are only available as built-in utilities will also not be considered.

With a shell that understands ${variable//pattern/word} for replacing a pattern with a string anywhere in a variable's value, and with a find that knows -maxdepth and -executable (kudos to isaac for mentioning this approach elsewhere):

(
    set -f
    find -H -- ${PATH//:/ } -maxdepth 1 -type f -name 'g*' -executable
)

This would turn off globbing for the find command, then search each of the directories listed in $PATH for any name starting with g that corresponds to an executable file. This would find executable by the current user only. Use -perm -o+x instead of -executable to test whether the executable bit is set for "others" instead.

The -H option for find will make it resolve symbolic links given on the command line (i.e. the search paths), but not the ones found while traversing the paths.


The above was a generic /bin/sh solution. If you are allowed to use special bash commands, you may generate a list of all external command, shell functions and aliases, that start with the letter g with

compgen -c g

To include built-in commands, use

compgen -bc g

... but this may count as "using bash completion".

The compgen built-in command is documented in the bash(1) manual.

Kusalananda
  • 333,661