I have a small shellscript, that can help me identify a command: what kind of command it is and if installed via a program package, which package. Maybe use the name what-about
,
#!/bin/bash
LANG=C
inversvid="\0033[7m"
resetvid="\0033[0m"
if [ $# -ne 1 ]
then
echo "Usage: ${0##*/} <program-name>"
echo "Will try to find corresponding package"
echo "and tell what kind of program it is"
exit 1
fi
command="$1"
str=;for ((i=1;i<=$(tput cols);i++)) do str="-$str";done
tmp="$command"
first=true
curdir="$(pwd)"
tmq=$(which "$command")
tdr="${tmq%/*}"
tex="${tmq##*/}"
if test -d "$tdr"; then cd "$tdr"; fi
#echo "cwd='$(pwd)' ################# d"
while $first || [ "${tmp:0:1}" == "l" ]
do
first=false
tmp=${tmp##*\ }
tmq="$tmp"
tmp=$(ls -l "$(which "$tmp")" 2>/dev/null)
tdr="${tmq%/*}"
tex="${tmq##*/}"
if test -d "$tdr"; then cd "$tdr"; fi
# echo "cwd='$(pwd)' ################# d"
if [ "$tmp" == "" ]
then
tmp=$(ls -l "$tex" 2>/dev/null)
tmp=${tmp##*\ }
if [ "$tmp" == "" ]
then
echo "$command is not in PATH"
# package=$(bash -ic "$command -v 2>&1")
# echo "package=$package XXXXX 0"
bash -ic "alias '$command' > /dev/null 2>&1" > /dev/null 2>&1
if [ $? -ne 0 ]
then
echo 'looking for package ...'
package=$(bash -ic "$command -v 2>&1"| sed -e '0,/with:/d'| grep -v '^$')
else
echo 'alias, hence not looking for package'
fi
# echo "package=$package XXXXX 1"
if [ "$package" != "" ]
then
echo "$str"
echo "package: [to get command '$1']"
echo -e "${inversvid}${package}${resetvid}"
fi
else
echo "$tmp"
fi
else
echo "$tmp"
fi
done
tmp=${tmp##*\ }
if [ "$tmp" != "" ]
then
echo "$str"
program="$tex"
program="$(pwd)/$tex"
file "$program"
if [ "$program" == "/usr/bin/snap" ]
then
echo "$str"
echo "/usr/bin/snap run $command # run $command "
sprog=$(find /snap/"$command" -type f -iname "$command" \
-exec file {} \; 2>/dev/null | sort | tail -n1)
echo -e "${inversvid}file: $sprog$resetvid"
echo "/usr/bin/snap list $command # list $command"
slist="$(/usr/bin/snap list "$command")"
echo -e "${inversvid}$slist$resetvid"
else
package=$(dpkg -S "$program")
if [ "$package" == "" ]
then
package=$(dpkg -S "$tex" | grep -e " /bin/$tex$" -e " /sbin/$tex$")
if [ "$package" != "" ]
then
ls -l /bin /sbin
fi
fi
if [ "$package" != "" ]
then
echo "$str"
echo " package: /path/program [for command '$1']"
echo -e "${inversvid} $package ${resetvid}"
fi
fi
fi
echo "$str"
#alias=$(grep "alias $command=" "$HOME/.bashrc")
alias=$(bash -ic "alias '$command' 2>/dev/null"| grep "$command")
if [ "$alias" != "" ]
then
echo "$alias"
fi
type=$(type "$command" 2>/dev/null)
if [ "$type" != "" ]
then
echo "type: $type"
elif [ "$alias" == "" ]
then
echo "type: $command: not found"
fi
cd "$curdir"
Sometimes there are two alternatives, e.g. for echo
, both a separate compiled program and shell built-in command. The shell built-in will get priority and be used unless you use the full path of the separate program,
$ what-about echo
-rwxr-xr-x 1 root root 35000 jan 18 2018 /bin/echo
----------------------------------------------------------------------------------
/bin/echo: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically
linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0,
BuildID[sha1]=057373f1356c861e0ec5b52c72804c86c6842cd5, stripped
----------------------------------------------------------------------------------
package: /path/program [for command 'echo']
coreutils: /bin/echo
----------------------------------------------------------------------------------
type: echo is a shell builtin
Sometimes a command is linked to program, that might be hidden, e.g. the version of rename
that I use,
$ what-about rename
lrwxrwxrwx 1 root root 24 maj 12 2018 /usr/bin/rename -> /etc/alternatives/rename
lrwxrwxrwx 1 root root 20 maj 12 2018 /etc/alternatives/rename -> /usr/bin/file-rename
-rwxr-xr-x 1 root root 3085 feb 20 2018 /usr/bin/file-rename
----------------------------------------------------------------------------------
/usr/bin/file-rename: Perl script text executable
----------------------------------------------------------------------------------
package: /path/program [for command 'rename']
rename: /usr/bin/file-rename
----------------------------------------------------------------------------------
type: rename is /usr/bin/rename
I have an alias for rm
in order to avoid mistakes, and the alias has priority over the program in PATH
. You can prefix with backslash, \rm
to skip the alias and run the program directly. (Please remember that the alias applies only for the specific user, and not for sudo
and other users, unless they have defined a similar alias.)
$ what-about rm
-rwxr-xr-x 1 root root 63704 jan 18 2018 /bin/rm
---------------------------------------------------------------------------
/bin/rm: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV),
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for
GNU/Linux 3.2.0, uildID[sha1]=864c9bbef111ce358b3452cf7ea457d292ba93f0,
stripped
---------------------------------------------------------------------------
package: /path/program [for command 'rm']
coreutils: /bin/rm
---------------------------------------------------------------------------
alias rm='rm -i'
type: rm is /bin/rm
Bash
has a shell built-intype ...
, which tells you where external commands are, and the type of anything else it recognises.type alias man fi type
for example.creat()
example aligns here, since it's not something you can directly call from a shell command line. (Of course pretty much any program might use it, same as a shell redirection like> somefile
, though then againcreat()
is redundant, as you might as well callopen()
with the appropriate flags, but in any case, you don't make system calls by name from the shell command line)ctypes.sh
... ;-)