# Is there a unix command that gives the minimum/maximum of two numbers?

I was looking for a command to limit numbers read in from `stdin`.

I wrote a little script for that purpose (critique is welcome), but I was wondering if there was not a standard command for this, simple and (I think) common use case.

My script which finds the minimum of two numbers:

``````#!/bin/bash
# \$1 limit

[ -z "\$1" ] && { echo "Needs a limit as first argument." >&2; exit 1; }

if [ "\$number" -gt "\$1" ]; then
echo "\$1"
else
echo "\$number"
fi
``````

`sort` and `head` can do this:

``````numbers=(1 4 3 5 7 1 10 21 8)
printf "%dn" "\${numbers[@]}" | sort -rn | head -1       # => 21
``````

You can define a function as

``````maxnum(){
if [ \$2 -gt \$1 ]
then
echo \$2
else
echo \$1
fi
}
``````

Call it as `maxnum 54 42` and it echoes `54`. You can add validation info inside the function (such as two arguments or numbers as arguments) if you like.

Too long for a comment:

While you can do these things e.g. with the `sort | head` or `sort | tail` combos, it seems rather suboptimal both resource- and error-handling-wise. As far as execution is concerned, the combo means spawning 2 processes just to check two lines. That seems to be a bit of an overkill.

The more serious problem is, that in most cases you need to know, that the input is sane, that is contains only numbers. @glennjackmann’s solution cleverly solves this, since `printf %d` should barf on non-integers. It won’t work with floats either (unless you change the format specifier to `%f`, where you will run into rounding problems).

`test \$1 -gt \$2` will give you indication of whether the comparison failed or not (exit status of 2 means there was an error during the test. Since this usually is a shell built-in, there is no additional process spawned – we’re talking of order of hundreds times faster execution. Works with integers only, though.

If you happen to need to compare a couple of floating point numbers, interesting option might be `bc`:

``````define x(a, b) {
if (a > b) {
return (a);
}
return (b);
}
``````

would be the equivalent of `test \$1 -gt \$2`, and using in in shell:

``````max () { printf '
define x(a, b) {
if (a > b) {
return (a);
}
return (b);
}
x(%s, %s)
' \$1 \$2 | bc -l
}
``````

is still almost 2.5 times faster than `printf | sort | head` (for two numbers).

If you can rely on GNU extensions in `bc`, then youcan also use the `read()` function to read the numbers directly into the `bc` sript.

You can compare just two numbers with `dc` like:

``````dc -e "[\$1]sM \$2d \$1<Mp"
``````

… where `"\$1"` is your max value and `"\$2"` is the number you would print if it is lesser than `"\$1"`. That also requires GNU `dc` – but you can do the same thing portably like:

``````dc <<MAX
[\$1]sM \$2d \$1<Mp
MAX
``````

In both of the above cases you can set the precision to something other than 0 (the default) like `\${desired_precision}k`. For both it is also imperative that you verify that both values are definitely numbers because `dc` can make `system()` calls w/ the `!` operator.

With the following little script (and the next) you should verify the input as well – like `grep -v !|dc` or something to robustly handle arbitrary input. You should also know that `dc` interprets negative numbers with a `_` prefix rather than a `-` prefix – because the latter is the subtraction operator.

Aside from that, with this script `dc` will read in as many sequential `n`ewline separated numbers as you would care to provide it, and print for each either your `\$max` value or the input, depending on which is the lesser of the wo:

``````dc -e "\${max}sm
[ z 0=? d lm<M p s0 lTx ]ST
[ ? z 0!=T q ]S?
[ s0 lm ]SM lTx"
``````

So… each of those `[` square bracketed `]` expanses is a `dc` string object that is `S`aved each to its respective array – any one of `T`, `?`, or `M`. Besides some few other things `dc` might do with a string, it can also e`x`ecute one as a macro. If you arrange it right a fully functioning little `dc` script is assembled simply enough.

`dc` works on a stack. All input objects are stacked each upon the last – each new input object pushing the last top object and all objects below it down on the stack by one as it is added. Most references to an object are to the top stack value, and most references pop that top of stack (which pulls all objects below it up by one).

Besides the main stack, there are also (at least) 256 arrays and each array element comes with a stack all its own. I don’t use much of that here. I just store the strings as mentioned so I can `l`oad them when wanted and e`x`ecute them conditionally, and I `s`tore `\$max`‘s value in the top of the `m` array.

Anyway, this little bit of `dc` does, largely, what your shell-script does. It does use the GNU-ism `-e` option – as `dc` generally takes its parameters from standard-in – but you could do the same like:

``````echo "\$script" | cat - /dev/tty | dc
``````

…if `\$script` looked like the above bit.

It works like:

• `lTx` – This `l`oads and e`x`ecutes the macro stored in the top of `T` (for test, I guess – I usually pick those names arbitrarily).
• `z 0=?``T`est then tests the stack depth w/ `z` and, if the stack is empty (read: holds 0 objects) it calls the `?` macro.
• `? z0!=T q` – The `?` macro is named for the `?` `dc` builtin command which reads a line of input from stdin, but I also added another `z` stack depth test to it, so that it can `q`uit the whole little program if it pulls in a blank line or hits EOF. But if it does `!`not and instead successfully populates the stack, it calls `T`est again.
• `d lm<M``T`est will then `d`uplicate the top of stack and compare it to `\$max` (as stored in `m`). If `m` is the lesser value, `dc` calls the `M` macro.
• `s0 lm``M` just pops the top of stack and dumps it to the dummy scalar `0` – just a cheap way of popping the stack. It also `l`oads `m` again before returning to `T`est.
• `p` – This means that if `m` is less than the current top of stack, then `m` replaces it (the `d`uplicate of it, anyway) and is here `p`rinted, else it does not and whatever the input was is `p`rinted instead.
• `s0` – Afterward (because `p` doesn’t pop the stack) we dump the top of stack into `0` again, and then…
• `lTx` – recursively `l`oad `T`est once more then e`x`ecute it again.

So you could run this little snippet and interactively type numbers at your terminal and `dc` would print back at you either the number you entered or the value of `\$max` if the number you typed was larger. It would also accept any file (such as a pipe) as standard input. It will continue the read/compare/print loop until it encounters a blank line or EOF.

Some notes about this though – I wrote this just to emulate the behavior in your shell function, so it only robustly handles the one number per line. `dc` can, however, handle as many space separated numbers per line as you would care to throw at it. However, because of its stack the last number on a line winds up being the first it operates on, and so, as written, `dc` would print its output in reverse if you printed/typed more than one number per line at it.The proper way to handle that is to store up a line in an array, then to work it.

Like this:

``````dc -e "\${max}sm
[ d lm<M la 1+ d sa :a z0!=A ]SA
[ la d ;ap s0 1- d sa 0!=P ]SP
[ ? z 0=q lAx lPx l?x ]S?
[q]Sq [ s0 lm ]SM 0sa l?x"
``````

But… I don’t know if I want to explain that in quite as much depth. Suffice it to say that as `dc` reads in each value on the stack it stores either its value or `\$max`‘s value in an indexed array, and, once it detects the stack is once again empty, it then prints each indexed object before attempting to read another line of input.

And so, while the first script does…

``````10 15 20 25 30    ##my input line
20
20
20
15
10                ##see what I mean?
``````

The second does:

``````10 15 20 25 30    ##my input line
10                ##that's better
15
20
20                ##\$max is 20 for both examples
20
``````

You can handle floats of arbitrary precision if you first set it with the `k` command. And you can alter the `i`nput or `o`utput radices independently – which can sometimes be useful for reasons you might not expect. For example:

``````echo 100000o 10p|dc
00010
``````

…which first sets `dc`‘s output radix to 100000 then prints 10.

If you know you are dealing with two integers `a` and `b`, then these simple shell arithmetic expansions using the ternary operator are sufficient to give the numerical max:

``````\$(( a > b ? a : b ))
``````

and numerical min:

``````\$(( a < b ? a : b ))
``````

E.g.

``````\$ a=10
\$ b=20
\$ max=\$(( a > b ? a : b ))
\$ min=\$(( a < b ? a : b ))
\$ echo \$max
20
\$ echo \$min
10
\$ a=30
\$ max=\$(( a > b ? a : b ))
\$ min=\$(( a < b ? a : b ))
\$ echo \$max
30
\$ echo \$min
20
\$
``````

Here is a shell script demonstrating this:

``````#!/usr/bin/env bash
[ -z "\$1" ] && { echo "Needs a limit as first argument." >&2; exit 1; }
echo Min: \$(( \$number  < \$1 ? \$number : \$1 ))
echo Max: \$(( \$number  > \$1 ? \$number : \$1 ))
``````

Most people would just do `sort -n input | head -n1` (or tail), it’s good enough for most scripting situations. However, this is a bit clumsy if you have numbers in a line instead of a column – you have to print it out in a proper format (`tr ' ' 'n'` or something similar).

Shells are not exactly ideal for numerical processing, but you can easily just pipe into some other program that is better in it. Depending on your own preference, you max call `dc` (a bit obfuscated, but if you know what you are doing, it’s fine – see mikeserv’s answer), or `awk 'NR==1{max=\$1} {if(\$1>max){max=\$1}} END { print max }'`. Or possibly `perl` or `python` if you prefer. One solution (if you are willing to install and use less known software) would be `ised` (especially if your data is in a single line: you just need to do `ised --l input.dat 'max\$1'`).

Because you are asking for two numbers, this is all overkill. This should be enough:

``````python -c "print(max(\$j,\$k))"
``````

You can define a library of predefined math functions for `bc` and then use them in the command line.

For example, include the following in a text file such as `~/MyExtensions.bc`:

``````define max(a,b){
if(a>b)
{
return(a)
}else{
return(b)
}
}
``````

Now you can call `bc` by:

``````> echo 'max(60,54)' | bc ~/MyExtensions.bc
60
``````

FYI, there are free math library functions such as this available online.

Using that file, you can easily calculate more complicated functions such as `GCD`:

``````> echo 'gcd (60,54)' | bc ~/extensions.bc -l
6
``````

To get the greater value of \$a and \$b use this:

``````[ "\$a" -gt "\$b" ] && \$a || \$b
``````

But you need something around that, you probably don’t mean to execute the number, so to display the greater value of the two use “echo”

``````[ "\$a" -gt "\$b" ] && echo \$a || echo \$b
``````

The above fits nicely into a shell function, eg

``````max() {
[ "\$1" -gt "\$2" ] && echo \$1 || echo \$2
}
``````

To assign the greater of the two to variable, use this modified version:

``````[ "\$a" -gt "\$b" ] && biggest=\$a || biggest=\$b
``````

or use the function defined:

``````biggest=\$( max \$a \$b )
``````

The function variation also gives you the opportunity to add input error checking neatly.

To return the max of two decimal / floating point numbers you can use `awk`

``````decimalmax() {
echo \$1 \$2 | awk '{if (\$1 > \$2) {print \$1} else {print \$2}}';
}
``````

EDIT: Using this technique you can create a “limit” function which operates the other way around as per your edit/note. This function will return the lower of the two, eg:

``````limit() {
[ "\$1" -gt "\$2" ] && echo \$2 || echo \$1
}
``````

I like to put utility functions into a separate file, call it `myprogram.funcs` and use it in a script as follow:

``````#!/bin/bash

# Initialization. Read in the utility functions
. ./myprogram.funcs

# Do stuff here
#
[ -z "\$1" ] && { echo "Needs a limit as first argument." >&2; exit 1; }

echo \$( limit \$1 \$number )
``````

FWIW this still does what you did, and your version even though it is more verbose, is just as efficient.

The more compact form is not really better, but prevents clutter in your scripts. If you have many simple if-then-else-fi constructs the script rapidly expands.

If you want to re-use the check for bigger/smaller numbers multiple times in a single script, put it in a function. The function format makes it easier to debug and re-use and allows you to easily replace that part of the script, for example with an awk command to be able to handle non-integer decimal numbers.

If it is a single use case, just code it in-line.

From a shell script, there is a way to use any Java public static method (and for instance Math.min()). From bash on Linux:

``````. jsbInit
jsbStart
A=2
B=3
C=\$(jsb Math.min "\$A" "\$B")
echo "\$C"
``````

This requires Java Shell Bridge https://sourceforge.net/projects/jsbridge/

Very fast, because the method calls are internally piped; no process required.

Quote from the OP’s question, emphasis mine:

I was wondering if there was not a standard command for this

In my opinion most of the answers missed OP’s point as they are all custom scripts and not standard solutions. Here are two solutions using tools specially made for the job. Usually, these tools are not pre-installed.

## General Solution For A List Of (Possibly Floating Point) Numbers, One Per Line

### Numbound from Num-Utils

To retrieve the minimum use `yourCommand | numbound -l`.
`-l` (lowercase L) stands for lower bound.

On Debian and Ubuntu `numbound` is installed using `apt install num-utils`. This package also includes similar tools for averaging numbers, summing them up and so on. The package description in `apt show num-utils` lists all of them:

`numaverage`, `numbound`, `numinterval`, `numnormalize`, `numgrep`, `numprocess`, `numsum`, `numrandom`, `numrange`, `numround`

### GNU Datamash

To retrieve the minimum use `yourCommand | datamash min 1`.
`1` (one) stands for the the first column in the input.

On Debian and Ubuntu `datamash` is installed using `apt install datamash`. This tool can do much more, see examples and the full manual.

For high portability and density consider `expr` – it has become my swiss army knife for tests that would otherwise involve `echo`ing the result and thus become unwieldy.

``````expr \$a & \$a > \$b | \$b
``````

Prints the larger of the two numbers – turn around the `>` to a `<` and get the smaller one ðŸ™‚

Note that this does not work for negative numbers.

Assuming this was for use in a Makefile

If you have a Guile-enable GNU Make version (such as available from GNU Guix), then you can simply use Guile, a powerful interpreted Scheme. Here’s a demonstration:

``````# file: Makefile

ifeq (\$(findstring guile,\$(.FEATURES)),)
\$(error "please install GNU Make compiled with Guile support")
endif

A ?= 5
B ?= 8

all:
@echo "max(A, B) is:" \$(guile (max \$(A) \$(B)))
``````
``````\$ make A=-25 B=-5
max(A, B) is: -5
``````

You can compute arbitrary complicated things. For more information regarding of this GNU Make feature, see `info '(make) Guile Integration'`. For the Guile reference manual, see `info (guile)`.

Have fun!