2

So as the question suggests, I want to get the version of a command inside a bash script, instead of using the terminal.

I know that all available commands are present as files inside the directory /usr/bin. But it does not give the versions and it gives some funny information when you use cat for one of the (command) files.

for example - cat /usr/bin/man gives -

funny output

What is this and how do I get the version?

I am using Ubuntu 20.04.

I know its a stupid question to ask here but I wasn't able to find anything :/

Supposedly the final edit - the accepted answer works for me, I am using the function.

I did also realise later that something like foo --version will work too

But, if you are using a variable to store the version then you need to be careful about the syntax, I was doing it the wrong way. Thanks to @Romeo Ninov for pointing out that
foo --version works too.

I am really sorry for these silly mistakes.

  • Regarding your recent update: Which answers can't be used in a script? – Kusalananda Jul 08 '22 at 08:54
  • i wouldn't say that they can't be used inside a script, I just don't know how to do it. – Antas Sharma Jul 08 '22 at 09:05
  • I have tried - to get the value of say, man -v inside a variable and then echo it out but it doesn't work. – Antas Sharma Jul 08 '22 at 09:07
  • Oh wait the first one works, my bad. – Antas Sharma Jul 08 '22 at 09:22
  • 3
    Formal note: the answer you accepted is not the first one chronologically. If you mean "the first answer from the top" then please note each user can choose a sorting method independently. Therefore the term "first answer" is not well-defined, in general it can easily confuse users who see different order of answers. For future reference: if you really need to address an answer anywhere else than in comments under the very answer, link to it. In this case we know what answer you probably mean: the accepted one. – Kamil Maciorowski Jul 08 '22 at 11:58
  • Oh I'll keep that in mind next time. Thanks for the tip – Antas Sharma Jul 08 '22 at 12:08
  • 1
    The main difference between an interactive shell session and a script is where it reads commands from (a terminal for the former, a file for the latter). – chepner Jul 08 '22 at 15:45
  • 1
    Please don't post images of text. They can be hard to read, impossible to search/index, and cannot be pasted into terminals to test. – doneal24 Jul 08 '22 at 17:50
  • Oh I thought it wouldn't be be of any use. Should I paste the output here then? – Antas Sharma Jul 08 '22 at 18:01

3 Answers3

7

If you are on a Debian based distribution, you can use the package manager to figure it out:

$ dpkg -S '*bin/man'
man-db: /usr/bin/man

This tells us man-db is the package which owns /usr/bin/man.

$ dpkg -l man-db
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name           Version      Architecture Description
+++-==============-============-============-=================================
ii  man-db         2.10.2-1     amd64        tools for reading manual pages

Then we ask what version of man-db is installed. This is man-db's upstream version 2.10.2 released by the distribution with an extra -1. The -1 represents a patch done by the distribution. This may just include build-rules, but could also include fixes to 2.10.2 ported from later versions.

dpkg-query can be used to extract the version:

$ dpkg-query -W -f '${Version}\n' man-db
2.10.2-1

Putting all this together:

$ dpkg-query -W -f '${Version}\n' $(dpkg -S '*bin/man' | cut -d: -f1)
2.10.2-1

Or a function which could go into .bashrc:

ver() {
  package=$(dpkg -S "*bin/$1" | cut -d: -f1)
  version=$(dpkg-query -W -f '${Version}' "$package")
  printf "%s\n" "$version"
}

ver man 2.10.2-1

(Behind the scenes, dpkg -S is really dpkg-query -S, but dpkg-query -S can't be combined with -W -f.)

Stephen Kitt
  • 434,908
Stewart
  • 13,677
5

AFAIK there is no firm single way to get the version from an arbitrary command foo (by running it or by analyzing the executable). Some foos may tell you something upon foo -v, others upon foo -V or foo --version, foo --help, foo -h, …; it's totally up to them (i.e. their authors).

Read the manual (man foo) to find out which of these options (if any, or yet another) the tool supports. The manual itself may tell you the version (usually at or near the bottom), but in this case it's the version of foo the manual describes, not necessarily the version of foo you can use. In a system where tools and their manuals are installed from repositories, these should correspond; but in general it's possible to get and use foo in a different version (or versions) than the manual describes.

The package system used by your distribution may provide you a firm way to see the versions of installed packages (examples for Debian and derivatives, including Ubuntu). If you know which package the tool you're after belongs to (again, for Debian and…), you can often deduce the version of the tool from the version of the package.

In general an executable may or may not be in a binary format; it may be a script for an arbitrary interpreter. There is no requirement for it to include its version anywhere in the file or to report in its output. In some cases the whole concept of versions does not apply. E.g. my script from this other answer has no version assigned to it. Similarly this wrapper I analyzed in yet another answer has no version (it came with a package that has a version though).

The conclusion is you cannot reliably get the version of an arbitrary executable from the executable itself; unless it's a particular executable and you tune your script to it (i.e. parse foo -V or whatever is right for this particular executable). You can get the version of a package.

I can see this concurrently written answer has provided a way to get the version of the package that owns a given executable. I won't reinvent it then.

  • I am trying to get the version inside a shell script instead of the terminal. For the terminal I guess it could be managed but I don't know for the shell script – Antas Sharma Jul 08 '22 at 08:56
  • 1
    @AntasSharma I gave you no shell code because this other answer beat me to it and I couldn't do significantly better. The code there is exactly for a shell like Bash, interactive or not; the ver function even sets shell variables you can use later without additional effort. – Kamil Maciorowski Jul 08 '22 at 09:06
  • Ah I realised later that it works in a shell script. Thanks – Antas Sharma Jul 08 '22 at 09:21
1

The usual way to get version of command is to use command like:

man --version

Be warned this can give you more than one line as answer so you should manage this. Also for each command you can check man page. For example:

man man

where you can see eventually the version. If you want to get it directly from the binary file you can try with

strings /usr/bin/man

and filter the result

Romeo Ninov
  • 17,484
  • 1
    Ah I've used the v flag but I don't know how to make it work inside a shell script. – Antas Sharma Jul 08 '22 at 08:57
  • 1
    @AntasSharma Why would it be any different inside a shell script? Programs can't generally tell the difference between running from the CLI and running from a script and they don't behave differently. – Barmar Jul 08 '22 at 13:58
  • 1
    Oh my god, it wasn't working for me because I was using a variable to store the variable and I didn't know the exact syntax for that. I made a file with just the command man --version and it worked. – Antas Sharma Jul 08 '22 at 17:32