Softpanorama
May the source be with you, but remember the KISS principle ;-)

Contents Bulletin Scripting in shell and Perl Network troubleshooting History Humor

Arithmetic Expressions in BASH

News

See also

Recommended  Links

Quoting caveats Double square bracket conditionals Single square bracket conditionals
Compound comparisons if statements in shell  Macro substitutions caveats Case statement in shell Bash Built-in Variables  
BASH Debugging Annotated List of Bash Enhancements bash Tips and Tricks Tips and Tricks Humor Etc

Introduction

Older UNIX shells like Borne shell  and ksh88 have clumsy, inefficient way of doing arithmetic based on external expr command:

z=`expr $z + 3` 

This was questionable decision even at the time when Unix run of machines with just 2MB of memory. Even at this time shell can be implemented in Forth (which was available since early 70th) with much richer capabilities. Charles Moore and Elizabeth Rather formed FORTH, Inc. in 1973, refining and porting Forth systems to dozens of platforms. Forth interpreter is really small; minimal is under 1KB

When Perl arrived, it became clear that classic Unix shell approach to arithmetic expressions is inferior on modern computers and actually increases overhead of shell instead of decreasing it. So ksh93 was created to fight back the lost ground. While it failed to stop Perl momentum and Perl replaced shell for larger scripts, ksh93 was a big improvement over all previous shells. Among innovation brought to shell world by ksh93 is this new type of arithmetic expressions. 

Later bash (starting from version 3.2) re-implemented most of the advanced features of ksh93 plus a couple of its own.  Currently bash is restricted to integer arithmetic, while ksh93 can do floating-point arithmetic as well.

In bash version 3.2 and later you can (and should) use $(( )) or let for integer arithmetic expressions and conditionals. The idea of ((...)) construct is similar to [[...]] construct  introduced in ksh88. It provides built in capabilities for arithmetic that are superior to calling external function expr (or test in case of conditionals).

All-in-all despite warts ((..)) capabilities represent a considerable improvement over what we used to have in older Unix shells and thus should be used whenever possible.  I would like to remind again that before ksh93 introduced let and (( ... )) commands, the only way to perform arithmetic was with expr. For example, to do the same increment to variable i you need to write:
i=`expr $i + 5` 
The ((...)) construct can (and should) be used in any control statements such as if, headers of loop and case statement. for example:
function mess
{
   if (( "$1" > 0 )) ; then
      total=$1
   else
      total=100
   fi
   tail -$total /var/adm/messages | more
}

New  ((...)) conditional expression  should always be used instead of expr function

The ((...)) conditional expression evaluates an arithmetic expression like it was written in a "normal" algorithmic language (you can even omit dollar signs from the variables within such an expression) and sets the exit status to 1 if the expression evaluates to 0, or to 0 if the expression evaluates to a non-zero value.  For example:

(( uid == 0 ))
(( uid > 1000 ))
(( i=i+1 ))

You can use multiple expressions connected with operations AND or OR. That make it the new standard was to program integer comparisons in if statements, while loops and similar control flow constructs. Old [[...]] construct should no longer be used for arithmetic expressions: it just does not make any sense anymore outside string comparisons.  For example

 (( percent >= 0 && percent <= 100 ))

Another  example:

 (( uid > 10  &&  uid < 100  )) # arithmetic condition

As long as you can limit yourself to integer arithmetic, you can use all the standard C-language operators inside of  ((...)) conditionals.

As long as you can limit yourself to integer arithmetic, you can use all the standard C-language operators inside of  ((...)) conditionals.

Here is a more complex examples, that demonstrates that it not always possible to get rid of leading $ in arithmetic expressions -- parameters still should contain it:

function mess
{
   if (( "$1" > 0 )) ; then
      total=$1
   else
      total=100
   fi
   tail -$total /var/adm/messages | more
}

Arithmetic operations

All arithmetic operations are performed  on integers. Syntax is similar to conditional expressions with some twists. For example:

i=$(( i + 1 ))
or
(( i=i+1 ))
(( i++ ))
let i+=1
let i++
i=$(( i++))
let i++

The assignments can  be cascaded, through the use of the comma operator:

	echo $(( i+=2 , j++ ))

which will do both assignments and then echo the result of the second expression (since the comma operator returns the value of its second expression).

Quotes or backslashes  usually are not needed  inside of the $(( )) construct:
all characters between the (( and )) are treated as string in double quotes.

 

If you use let ( and I do not recomment using let for anything but C-style shorcut operators like += and ++) it is prudent to put expression in double quote to avoid conflict with bash metasymbols such as "*", '('  and ')'.
 

If you use let ( and I do not recomment using let for anything but C-style shorcut operators like += and ++) it is prudent to put expression in double quote to avoid conflict with bash metasymbols such as "*", '('  and ')'.

Shortcuts for assignment operators in bash

Most of C-style shortcuts operators are now supported by BASH. The most useful is probably  +=  (familiar to any C programmer). That means that:

let i=$i+5

can be written as

let i+=5
Usual C-style increments/decrements  ++/--  are available  too:
let $i++
or
(( $i++ ))

Here is an extended table of available shortcuts:

Operator Operation with assignment Use Meaning
= Simple assignment a=b a=b
*= Multiplication a*=b a=(a*b)
/= Division a/=b a=(a/b)
%= Remainder a%=b a=(a%b)
+= Addition a+=b a=(a+b)
-= Subtraction a-=b a=(a-b)
<<= Bit-shift left a<<=b a=(a<<b)
>>= Bit-shift right a>>=b a=(a>>b)
&= Bitwise "and" a&=b a=(a&b)
^= Bitwise "exclusive or" a^=b a=(a^b)
|= Bitwise "or" a|=b a=(a|b)

The differences between the ((...)) command and let command

While constructs are almost identical there some minor differences. I would prefer to use ((..)) in both conditional expressions  and assignment statements as let construct contains a couple of unpleasant gotchas:

Ternary operator ?

In C ?: is a ternary operator that provides capabilities for a basic conditional expression. It is commonly referred to as the conditional operator, inline if (iif), or ternary if.

A traditional if-else construct in C  is written:

if (a >= b) {
    max = a;
} else {
    max = b;
}

This can be rewritten as the following statement:

max = a >= b ? a : b;

Although many ternary operators are possible, only conditional operator is common. Other ternary operators so rare, that the conditional operator is commonly referred to as the ternary operator.

It is now re-implemented and is available in bash. The example above can be written as

let "max = a >= b ? a : b" # note usage of double quotes
or better
 (( max = a >= b ? a : b )) 

For example:

a=6 
b=5
let "max = a >= b ? a : b"   # Condition is true
echo $max

let "b += 2"
let "max = a > b ? a : b"   # Condition is false
echo $max 
Here is a relevant discussion in Stack Overflow

Q: Is there a way to do something like this

int a = (b == 5) ? c : d;

using Bash?

Daniel Daranas asked Oct 17 '10 at 14:38 

A: Code:

   a=$(( b == 5 ? c : d )) 
   
answered Oct 17 '10 at 14:53  by Vladimir

A: ternary operator ? : is just short form of if/else

case "$b" in 
   5) a=$c ;; 
   *) a=$d ;; 
   esac

Or

a="$d"; [[ $b = 5 ]] && a="$c" 

down vote for [ $b == 5 ] && a=$c || a=$d

this solution is incorrect !!! Watch out with this construct, as the part after the || is also executed when the part between && and || fails. Use

[ $b == 5 ] && { a=$c; true; } || a=$d – James Andino Nov 22 '13 at 23:14

This will avoid executing the part after || by accident when the code between && and || fails.

If the condition is merely checking if a variable is set, there's even a shorter form:
a=${VAR:-20}

will assign to a the value of VAR if VAR is set, otherwise it will assign it the default value 20 -- this can also be a result of an expression. As alex notes in the comment, this approach is technically called "Parameter Expansion".

(( a = b==5 ? c : d )) # string + numeric

This is good for numeric comparisons and assignments, but it will give unpredictable results if you use it for string comparisons and assignments.... (( )) treats any/all strings as 0 – Peter.O May 12 '11 at 22:51

(ping -c1 localhost&>/dev/null) && { echo "true", true; } || { echo "false"; }
The let command supports most of the basic operators one would need:
let a = b==5 ? c : d;

Naturally, this works only for assigning variables; it cannot execute other commands.

it is exactly equivalent to (( ... )), so it is only valid for arithmetic expressions – AlberT Jan 30 '13 at 12:07

Here is another option where you only have to specify the variable you're assigning once, and it doesn't matter whether what your assigning is a string or a number:
VARIABLE=`[ test ] && echo VALUE_A || echo VALUE_B`

Just a thought. :)

down vote

if [ "$b" -eq 5 ]; then a="$c"; else a="$d"; fi

The cond && op1 || op2 solution suggested in other answers has an inherent bug: if op1 has a nonzero exit status, op2 silently becomes the result; the error will also not be catched in -e mode.

Gotchas

 (( )) treats any strings as 0. If any of the variable has string value you might have a problem.

Generally in shells line bash or ksh93 spaces are treated as in any normal algorithmic language: they are optional.  But this is not always the case. Spaces before and after equal sign have a special meaning. And that a gotcha that you need to be aware of: a space before equal sign confuses bash into thinking that this is a function invocation. For example, in case of

i = $(( i + 5 )) # not what you think!

bash will try to run a program named i and its first argument would be an equal sign, and its second argument would be the number you get adding 5 to the value of $i.

Spaces before and after equal sign have a special meaning: a space before equal sign confuses bash into thinking that this is a function invocation

Another idiosyncrasy is that so called shell   R-value rule ($ should be prefixed to the shell variable on the right side of assignment statement to get its value) is now optional and generally you should probably omit $ prefix for variables in ((..)) construct.  That means that

let i=$i+1

can be written as in regular programming languages:

let i=i+1 

The gotcha is that you still need the dollar sign for positional parameters (e.g.,$2) to distinguish it from a numeric constant (e.g., "2"). Here's an example:

i=$(( i + $2 ))

Additional examples

Instant integer calculator using the echo command. for example for conversion of megabytes in kilobytes and bytes

echo $(( 33*1024 ))

Additional examples from Internal Commands and Builtins

let a=11            # Same as 'a=11'
let a=a+5           # Equivalent to  let "a = a + 5"
                    # (Double quotes and spaces make it more readable.)
echo "sum of 11 + 5 is $a"  # 16

let "a <<= 3"       # Equivalent to  let "a = a << 3"
echo "\"\$a\" (=16) left-shifted 3 places = $a"
                    # 128

let "a /= 4"        # Equivalent to  let "a = a / 4"
echo "128 / 4 = $a" # 32

let "a -= 5"        # Equivalent to  let "a = a - 5"
echo "32 - 5 = $a"  # 27

let "a *=  10"      # Equivalent to  let "a = a * 10"
echo "27 * 10 = $a" # 270

let "a %= 8"        # Equivalent to  let "a = a % 8"
echo "270 modulo 8 = $a  (270 / 8 = 33, remainder $a)"
                    # 6
C-style shortcuts
let a++             # C-style (post) increment.
let a--             # C-style decrement.
# Of course, ++a, etc., also allowed . . .

Using Array Variables

Bash, at last, provides one-dimensional indexed and associative array variables. They can be declared implicitly (contextually) or explicitly. To explicitly declare an array, use

     declare -a name

Initialization of arrays in bash has format similar to Perl:

	solaris=(serv01 serv02 serv07 ns1 ns2)

Each element of the array is a separate word in the list enclosed in parentheses. Then you can refer to each as ${solaris[0]}, ${solaris[1]}, ${solaris[2]} ...:

	echo solaris10 is installed on ${solaris[2]}

If you omit index and use command "echo $solaris" you will get the first element of array too.

Another example taken from Bash Shell Programming in Linux
array=(red green blue yellow magenta)
size=${#array[*]}
echo "The array has $size members. They are:"
i=0
while (( i < $size )); do
   echo "$i: ${array[$i]}"
   let i++
done                                                                
Run this example:
$ ./myscript.sh
The array has 5 members. They are:
0: red
1: green
2: blue
3: yellow
4: magenta

The (( ...)) construct is also used in bash for a new, classic C-style form of  for loop syntax, one that looks a lot like C Language:

for (( i=1; i<=n; i++ ))
do
   touch file$i
done

for (( ; ; ))
do
   echo "infinite loop [ hit CTRL+C to stop]"
done

Its more general form this new, C-style loop can be described as:

for (( expr1 ; expr2 ; expr3 )) ; do list ; done

The use of double parentheses indicates that expressions can use syntax of ((..)) construct

Several iteration counters can be used. For example:

	
for (( i=0, j=0 ; i < 10 ; i++, j++ ))
do
    echo $((i*j))
done

That for loop initializes two variables (i and j), then increments them both. The comma operator is used in the first and the third expressions.

Here are some additional examples from Advanced Bash scripting guide:

Example 10-12. A C-like for loop
for ((a=1; a <= LIMIT ; a++))  # Double parentheses, and "LIMIT" with no "$".
do
  echo -n "$a "
done                           # A construct borrowed from 'ksh93'.

echo; echo

# +=========================================================================+

# Let's use the C "comma operator" to increment two variables simultaneously.

for ((a=1, b=1; a <= LIMIT ; a++, b++))  # The comma chains together operations.
do
  echo -n "$a-$b"
done

echo; echo

exit 0

Mitch Frazier in his article Bash Arrays published in Linux Journal (Jun 19, 2008) provides some additional information

If you're used to a "standard" *NIX shell you may not be familiar with bash's array feature. Although not as powerful as similar constructs in the P languages (Perl, Python, and PHP) and others, they are often quite useful.

Bash arrays have numbered indexes only, but they are sparse, ie you don't have to define all the indexes. An entire array can be assigned by enclosing the array items in parenthesis:

  arr=(Hello World)
Individual items can be assigned with the familiar array syntax (unless you're used to Basic or Fortran):
  arr[0]=Hello
  arr[1]=World
But it gets a bit ugly when you want to refer to an array item:
  echo ${arr[0]} ${arr[1]}
To quote from the man page:
The braces are required to avoid conflicts with pathname expansion.

In addition the following funky constructs are available:

  ${arr[*]}         # All of the items in the array
  ${!arr[*]}        # All of the indexes in the array
  ${#arr[*]}        # Number of items in the array
  ${#arr[0]}        # Length if item zero
The ${!arr[*]} is a relatively new addition to bash, it was not part of the original array implementation.

The following example shows some simple array usage (note the "[index]=value" assignment [5]=five below  to assign a specific index):

#!/bin/bash

array=(one two three four [5]=five)

echo "Array size: ${#array[*]}"

echo "Array items:"
for item in ${array[*]}
do
    printf "   %s\n" $item
done

echo "Array indexes:"
for index in ${!array[*]}
do
    printf "   %d\n" $index
done

echo "Array items and indexes:"
for index in ${!array[*]}
do
    printf "%4d: %s\n" $index ${array[$index]}
done
Running it produces the following output:
Array size: 5
Array items:
   one
   two
   three
   four
   five
Array indexes:
   0
   1
   2
   3
   5
Array items and indexes:
   0: one
   1: two
   2: three
   3: four
   5: five

Note that the "@" sign can be used instead of the "*" in constructs such as ${arr[*]}, the result is the same except when expanding the items of the array within a quoted string. In this case the behavior is the same as when expanding "$*" and "$@" within quoted strings: "${arr[*]}" returns all the items as a single word, whereas "${arr[@]}" returns each item separately: one item one word.

The following example shows how unquoted, quoted "*", and quoted "@" affect the expansion (particularly important when the array items themselves contain spaces):

#!/bin/bash

array=("first item" "second item" "third" "item")

echo "Number of items in original array: ${#array[*]}"
for ix in ${!array[*]}
do
    printf "   %s\n" "${array[$ix]}"
done
echo

arr=(${array[*]})
echo "After unquoted expansion: ${#arr[*]}"
for ix in ${!arr[*]}
do
    printf "   %s\n" "${arr[$ix]}"
done
echo

arr=("${array[*]}")
echo "After * quoted expansion: ${#arr[*]}"
for ix in ${!arr[*]}
do
    printf "   %s\n" "${arr[$ix]}"
done
echo

arr=("${array[@]}")
echo "After @ quoted expansion: ${#arr[*]}"
for ix in ${!arr[*]}
do
    printf "   %s\n" "${arr[$ix]}"
done
When run it outputs:
Number of items in original array: 4
   first item
   second item
   third
   item

After unquoted expansion: 6
   first
   item
   second
   item
   third
   item

After * quoted expansion: 1
   first item second item third item

After @ quoted expansion: 4
   first item
   second item
   third
   item

Mitch Frazier is the System Administrator at Linux Journal.

 

History

The man page for bash v3.2.48 says:

[...] The format for arithmetic expansion is: $((expression))

The old format $[expression] is deprecated and will be removed in upcoming versions of bash. So $[...] is old syntax that should not be used anymore.

The feature has been deprecated since bash-2.0, but persists till today (bash-4.2).

History of this feature is explained in the old email from the  bug-bash mailing list. http://lists.gnu.org/archive/html/bug-bash/2012-04/msg00033.html 

“In early proposals, a form $[expression] was used. It was functionally equivalent to the "$(())" of the current text, but objections were lodged that the 1988 KornShell had already implemented "$(())" and there was no compelling reason to invent yet another syntax.

Furthermore, the "$[]" syntax had a minor incompatibility involving the patterns in case statements.”

Dr. Nikolai Bezroukov


Top updates

Softpanorama Switchboard
Google Search


NEWS CONTENTS

Old News ;-)

Please visit Heiner Steven's SHELLdorado, the best shell scripting site on the Internet

[May 02, 2015] shell - Parenthesis in bash arithmetic 3 (2 + 1)

Unix & Linux Stack Exchange

Parenthesis in bash arithmetic: 3 * (2 + 1)

expr does not seem to like parenthesis (used in mathematics to explicit operator priority):
expr 3 * (2 + 1)
bash: syntax error near unexpected token `('

How to express operator priority in bash?

/ bash / shell / quoting / arithmetic

asked Aug 12 '14 at 6:09 by Nicolas Raoul

Another way to use let bash builtin:
$ let a="3 * (2 + 1)"
$ printf '%s\n' "$a"

Note

As @Stéphane Chazelas pointed out, in bash you should use ((...)) to do arithmetic over expr or let for legibility.

For portability, use $((...)) like @Bernhard answer.

cuonglm

+1 Even more readable! I posted my question+answer just thinking it would be helpful for my fellow Linux users, but now I am getting a lot of benefit from the other answers :-) – Nicolas Raoul Aug 12 '14 at 6:52

There's no reason to be using let. It's not any more standard or portable than (( a = 3 * (2 + 1) )) (both come from ksh and are only available in ksh, bash and zsh) and it's less legible or easy to quote. Use a=$((3 * (2 + 1))) to be portable. – Stéphane Chazelas Aug 12 '14 at 15:27

I'm not saying it's wrong, I'm just saying it should not be used as there are better alternatives (one for legibility ((a = 3 * (2 + 1) )), one for portability a=$((3 * (2 + 1)))), so it's not a note against you or your answer but against it being the selected answer and top-scorer. – Stéphane Chazelas Aug 12 '14 at 15:48

@StéphaneChazelas: Updated my answer! – cuonglm Aug 12 '14 at 16:19

You can use the arithmetic expansion instead.
echo "$(( 3 * ( 2 + 1 ) ))"

In my personal opinion, this looks a bit nicer than using expr. From man bash

Arithmetic Expansion Arithmetic expansion allows the evaluation of an arithmetic expression and the substitution of the result. The format for arithmetic expansion is:
$((expression))

The expression is treated as if it were within double quotes, but a double quote inside the parentheses is not treated specially. All tokens in the expression undergo parameter expansion, string expansion, command substitution, and quote removal. Arithmetic expansions may be nested.

The evaluation is performed according to the rules listed below under ARITHMETIC EVALUATION. If expression is invalid, bash prints a message indicating failure and no substitution occurs.

edited Dec 9 '14 at 19:39, by Stéphane Chazelas

Aside from readability, it also doesn't require forking an extra process to do the arithmetic; it's handled by the shell itself. – chepner Aug 12 '14 at 12:02

Note that in POSIX shells, it's subject to word splitting, so it's a good habit to quote it in list contexts.

– Stéphane Chazelas Aug 12 '14 at 15:57

Use parenthesis with quotes:

expr 3 '*' '(' 2 '+' 1 ')'

The quotes prevent bash from interpreting the parenthesis as bash syntax.

Nicolas Raoul

What Nicolas illustrates but doesn't explain is that the tokens on the expr command line must be separated by spaces; so; for example, expr 3 "*" "(2" "+" "1)" will not work. (Also, BTW, you probably don't need to quote the +.)

– G-Man Aug 12 '14 at 17:28

The parentheses aren't keywords like while and [[, they're syntax. If they were keywords, they wouldn't be interpreted as such in command arguments. You need quotes so that bash doesn't parse them but instead sees a string literal.

– Gilles Aug 13 '14 at 1:31

@Gilles: Thanks, updated! – Nicolas Raoul Aug 13 '14 at 1:55

There's no reason to be using expr for arithmetic in modern shells.

POSIX defines the $((...)) expansion operator. So you can use that in all POSIX compliant shells (the sh of all modern Unix-likes, dash, bash, yash, mksh, zsh, posh, ksh...).
a=$(( 3 * (2 + 1) ))
a=$((3*(2+1)))

ksh also introduced a let builtin which is passed the same kind of arithmetic expression, doesn't expand into something but returns an exit status based on whether the expression resolves to 0 or not, like in expr:
if let 'a = 3 * (2 + 1)'; then
echo "$a is non-zero"
fi

However, as the quoting makes it awkward and not very legible (not to the same extent as expr of course), ksh also introduced a ((...)) alternative form:
if (( a = 3 * (2 + 1) )) && (( 3 > 1 )); then
echo "$a is non-zero and 3 > 1"
fi
((a+=2))

which is a lot more legible and should be used instead.

let and ((...)) are only available in ksh, zsh and bash. The $((...)) syntax should be preferred if portability to other shells is needed, expr is only needed for pre-POSIX Bourne-like shells (typically the Bourne shell or early versions of the Almquist shell).

On the non-Bourne front, there are a few shells with built-in arithmetic operator:

•csh/tcsh (actually the first Unix shell with arithmetic evaluation built-in):
@ a = 3 * (2 + 1)


•akanga (based on rc)
a = $:'3 * (2 + 1)'


•as a history note, the original version of the Almquist shell, as posted on usenet in 1989 had an expr builtin (actually merged with test), but it was removed later.

answered Aug 12 '14 at 15:41 by Stéphane Chazelas

I learn something new every day from you, Stéphane. I very much appreciate your POSIX shell knowledge! – MattBianco Aug 21 '14 at 8:50

expr is an external command, it is not special shell syntax. Therefore, if you want expr to see shell special characters, you need to protect them from shell parsing by quoting them. Furthermore, expr needs each number and operator to be passed as a separate parameter. Thus:
expr 3 \* \( 2 + 1 \)

Unless you're working on an antique unix system from the 1970s or 1980s, there is very little reason to use expr. In the old days, shells didn't have a built-in way to perform arithmetic, and you had to call the expr utility instead. All POSIX shells have built-in arithmetic via the arithmetic expansion syntax.
echo $((3 * (2 + 1)))

The construct $((…)) expands to the result of the arithmetic expression (written in decimal). Bash, like most shells, supports only integer arithmetic modulo 264 (or modulo 232 for older versions of bash and some other shells on 32-bit machines).

Bash offers an additional convenience syntax when you want to perform assignments or to test whether an expression is 0 but don't care about the result. This construct also exists in ksh and zsh but not in plain sh.

((x = 3 * (2+1)))
echo "$x"
if ((x > 3)); then …

In addition to integer arithmetic, expr offers a few string manipulation functions. These too are subsumed by features of POSIX shells, except for one: expr STRING : REGEXP tests whether the string matches the specified regexp.

A POSIX shell cannot do this without external tools, but bash can with [[ STRING =~ REGEXP ]] (with a different regexp syntax — expr is a classic tool and uses BRE, bash uses ERE).

Unless you're maintaing scripts that run on 20-year-old systems, you don't need to know that expr ever existed. Use shell arithmetic.

- Gilles

expr foo : '\(.\)' also does text extraction. bash's BASH_REMATCH achieves something similar. It also does string comparison, which POSIX [ does not do (though one could imagine ways to use sort for that).

– Stéphane Chazelas Aug 15 '14 at 11:25

[May 02, 2015] ArithmeticExpression

2014-02-13 | Greg's Wiki

Arithmetic in BASH is integer math only. You can't do floating point math in Bash; if you need that capability, see Bash FAQ #22.

Also see the Bash hackers article about the full syntax theory. /!\ The $[ ] syntax is deprecated

There are several ways to tell Bash to treat numbers as integers instead of strings, and to do basic arithmetic operations on them. The first is to use the let command:

let a=17+23
echo "a = $a"      # Prints a = 40

Note that each arithmetic expression has to be passed as a single argument to the let command, so you need quotes if there are spaces or globbing characters, thus:

let a=17 + 23      # WRONG
let a="17 + 23"    # Right
let 'a = 17 + 23'  # Right
let a=17 a+=23     # Right (2 arithmetic expressions)

let a[1]=1+1       # Wrong (try after touch a1=1+1 or with shopt -s failglob)
let 'a[1]=1+1'     # Right
let a\[1]=1+1      # Right

Division in Bash is integer division, and it truncates the results, just as in C:

let a=28/6
echo "a = $a"      # Prints a = 4

In addition to the let command, one may use the (( )) syntax to enforce an arithmetic context. If there is a $ (dollar sign) before the parentheses, then a substitution is performed (more on this below). White space is allowed inside (( )) with much greater leniency than with let, and variables inside (( )) don't require $ (because string literals aren't allowed). Examples:

((a=$a+7))         # Add 7 to a
((a = a + 7))      # Add 7 to a.  Identical to the previous command.
((a += 7))         # Add 7 to a.  Identical to the previous command.

((a = RANDOM % 10 + 1))     # Choose a random number from 1 to 10.
                            # % is modulus, as in C.

# (( )) may also be used as a command.  > or < inside (( )) means
# greater/less than, not output/input redirection.
if ((a > 5)); then echo "a is more than 5"; fi

(( )) without the leading $ is not a standard sh feature. It comes from ksh and is only available in ksh, Bash and zsh. $(( )) substitution is allowed in the POSIX shell. As one would expect, the result of the arithmetic expression inside the $(( )) is substituted into the original command. Like for parameter substitution, arithmetic substitution is subject to word splitting so should be quoted to prevent it when in list contexts. Here are some examples of the use of the arithmetic substitution syntax:

a=$((a+7))         # POSIX-compatible version of previous code.
if test "$((a%4))" = 0; then ...
lvcreate -L "$((4*1096))" -n lvname vgname   # Actual HP-UX example.

Variables may be declared as integers so that any subsequent assignments to them will always assume a numeric context. Essentially any variable that's declared as an integer acts as if you had a let command in front of it when you assign to it. For example:

unset b             # Forget any previous declarations
b=7+5; echo "$b"    # Prints 7+5
declare -i b        # Declare b as an integer
b=7+5; echo "$b"    # Prints 12

Also, array indices are a numeric context:

n=0
while read line; do
   array[n++]=$line      # array[] forces a numeric context
done

There is one common pitfall with arithmetic expressions in Bash: numbers with leading zeroes are treated as octal. For example,

# Suppose today is September 19th.
month=$(date +%m)
next_month=$(( (month == 12) ? 1 : month+1 ))
# bash: 09: value too great for base (error token is "09")

This causes great confusion among people who are extracting zero-padded numbers from various sources (although dates are by far the most common) and then doing math on them without sanitizing them first. (It's especially bad if you write a program like this in March, test it, roll it out... and then it doesn't blow up until August 1.)

If you have leading-zero problems with Bash's built-in arithmetic, there are two possible solutions. The first is, obviously, to remove the leading zeroes from the numbers before doing math with them. This is not trivial in Bash, unfortunately, because Bash has no ability to perform substitutions on a variable using regular expressions (it can only do it with "glob" patterns). But you could use a loop:

# This removes leading zeroes from a, one at a time.
while [[ $a = 0* ]]; do a=${a#0}; done

You can do the above without using a loop, by using extended globs; see FAQ #67 for more information. Or, you could use sed; that may be more efficient if you're reading many numbers from a stream, and can arrange to sanitize them all in one command, rather than one by one.

Without a loop:

# This removes leading zeroes from a, all at once.
a=${a##+(0)}

The third solution is to force Bash to treat all numbers as base 10 by prefixing them with 10#. This might be more efficient, but also may be less elegant to read.

a=008
let b=a+1       # Generates an error because 008 is not valid in octal.
let b=10#$a+1   # Force a to be treated as base 10.  Note: the $ is required.

Finally, a note on the exit status of commands, and the notions of "true" and "false", is in order. When bash runs a command, that command will return an exit status from 0 to 255. 0 is considered "success" (which is "true" when used in the context of an if or while command). However, in an arithmetic context, there are places where the C language rules (0 is false, anything else is true) apply.

Some examples:

true; echo "$?"       # Writes 0, because a successful command returns 0.
((10 > 6)); echo "$?" # Also 0.  An arithmetic command returns 0 for true.
echo "$((10 > 6))"    # Writes 1.  An arithmetic expression returns 1 for true.

In addition to a comparison returning 1 for true, an arithmetic expression that evaluates to a non-zero value is also true in the sense of a command.

if ((1)); then echo true; fi     # Writes true.

This also lets you use "flag" variables, just like in a C program:

found=0
while ...; do
   ...
  if something; then found=1; fi    # Found one!  Keep going.
   ...
done
if ((found)); then ...

Here is a function to convert numbers in other bases to decimal (base 10):

todec() {
    echo "$(( $1#$2 ))"
}

Examples:

todec 16 ffe    # -> 4094
todec 2 100100  # -> 36

[Nov 21, 2010] Integer Arithmetic

Both Bash and the Korn shell support evaluating arithmetic expressions without arithmetic expansion. The syntax is similar to $((...)) but without the dollar sign. Because expansion is not performed, the construct can be used without variable assignment or the colon operator:

$ x=10
$ ((x = x * 12))
$ echo $x
120
$

The real value of this construct is that it allows arithmetic expressions to be used rather than test in if, while, and until commands. The comparison operators set the exit status to a nonzero value if the result of the comparison is false and to a zero value if the result is true. So writing

(( i == 100 ))

has the effect of testing i to see whether it is equal to 100 and setting the exit status appropriately. This knowledge makes integer arithmetic ideal for inclusion in if commands:

if (( i == 100 ))
then
       ...
fi

The (( i == 100 )) returns an exit status of zero (true) if i equals 100 and one (false) otherwise, and has the same effect as writing

if [ "$i" -eq 100 ]
then
        ...
fi

One advantage of using ((...)) rather than test is the capability to perform arithmetic as part of the test:

if (( i / 10 != 0 ))
then
    ...
fi

Here the comparison returns a true if i divided by 10 is not equal to zero.

while loops can also benefit from integer arithmetic. For example,

x=0
while ((x++ < 100))
do
      commands
done

executes commands 100 times. (Note that some older versions of the Korn shell and Bash do not support the ++ and -- operators.)

Integer Types

The Korn shell and Bash both support an integer data type. You can declare variables to be integers by using the typeset command with the -i option

typeset -i variables

where variables are any valid shell variable names. Initial values can be assigned to the variables at the time they are declared.

Arithmetic performed on integer variables with the ((...)) construct is slightly faster than on noninteger ones because the shell internally stores the value of an integer variable as a binary number and not as a character string.

An integer variable cannot be assigned anything but an integer value or an integer expression. If you attempt to assign a noninteger to it, the message bad number is printed by the Korn shell:

$ typeset -i i
$ i=hello
ksh: i: bad number

Bash simply ignores any strings that don't contain numeric values and generates an error for anything that contains both numbers and other characters:

$ typeset -i i
$ i=hello
$ echo $i
0
$ i=1hello
bash: 1hello: value too great for base (error token is "1hello")
$ i=10+15
$ echo $i
25
$

The preceding example shows that integer-valued expressions can be assigned to an integer variable, without even having to use the ((...)) construct. This holds true for both Bash and the Korn shell.

Numbers in Different Bases

The Korn shell and Bash allow you to perform arithmetic in different bases. To write a number in a different base with these shells, you use the notation

base#number

For example, to express the value 100 in base 8 (octal) you write

8#100

You can write constants in different bases anywhere an integer value is permitted. To assign octal 100 to the integer variable i, you can write

typeset -i i=8#100

Note that with the Korn shell the base of the first value assigned to an integer variable fixes the base of all subsequent substitutions of that variable. In other words, if the first value you assign to the integer variable i is an octal number, each time you subsequently substitute the value of i on the command line, the Korn shell substitutes the value as an octal number using the notation 8#value.

$ typeset -i i=8#100
$ echo $i
8#100
$ i=50
$ echo $i
8#62
$ (( i = 16#a5 + 16#120 ))
$ echo $i
8#705

Because the first value assigned to i in this example is an octal number (8#100), all further substitutions of i will be in octal. When the base 10 value of 50 is next assigned to i and then i is subsequently displayed, we get the value 8#62, which is the octal equivalent of 50 in base 10.

In the preceding example, the ((...)) construct is used to add together the two hexadecimal values a5 and 120. The result is then displayed, once again in octal.

Bash uses both the base#number syntax for arbitrary bases and the C language syntax for octal and hexadecimal numbers—octal numbers are preceded by 0 (zero), and hexadecimal numbers are preceded by 0x:

$ typeset -i i=0100
$ echo $i
64
$ i=0x80
$ echo $i
128
$ i=2#1101001
$ echo $i
105
$ (( i = 16#a5 + 16#120 ))
$ echo $i
453
$

Unlike the Korn shell, Bash doesn't keep track of the variable's base; integer variables are displayed as decimal numbers. You can always use printf to print integers in octal or hexadecimal format.

[Nov 21, 2010] Advanced Bash Shell Scripting Guide - Operators

Arithmetic operators often occur in an expr or let expression.

Example 8-2. Using Arithmetic Operations

#!/bin/bash
# Counting to 11 in 10 different ways.

n=1; echo -n "$n "

let "n = $n + 1"   # let "n = n + 1"  also works.
echo -n "$n "


: $((n = $n + 1))
#  ":" necessary because otherwise Bash attempts
#+ to interpret "$((n = $n + 1))" as a command.
echo -n "$n "

(( n = n + 1 ))
#  A simpler alternative to the method above.
#  Thanks, David Lombard, for pointing this out.
echo -n "$n "

n=$(($n + 1))
echo -n "$n "

: $[ n = $n + 1 ]
#  ":" necessary because otherwise Bash attempts
#+ to interpret "$[ n = $n + 1 ]" as a command.
#  Works even if "n" was initialized as a string.
echo -n "$n "

n=$[ $n + 1 ]
#  Works even if "n" was initialized as a string.
#* Avoid this type of construct, since it is obsolete and nonportable.
#  Thanks, Stephane Chazelas.
echo -n "$n "

# Now for C-style increment operators.
# Thanks, Frank Wang, for pointing this out.

let "n++"          # let "++n"  also works.
echo -n "$n "

(( n++ ))          # (( ++n )  also works.
echo -n "$n "

: $(( n++ ))       # : $(( ++n )) also works.
echo -n "$n "

: $[ n++ ]         # : $[ ++n ]] also works
echo -n "$n "

echo

exit 0
Integer variables in Bash are actually signed long (32-bit) integers, in the range of -2147483648 to 2147483647. An operation that takes a variable outside these limits will give an erroneous result.
a=2147483646
echo "a = $a"      # a = 2147483646
let "a+=1"         # Increment "a".
echo "a = $a"      # a = 2147483647
let "a+=1"         # increment "a" again, past the limit.
echo "a = $a"      # a = -2147483648
                   #      ERROR (out of range)

As of version 2.05b, Bash supports 64-bit integers. Bash does not understand floating point arithmetic. It treats numbers containing a decimal point as strings.

a=1.5

let "b = $a + 1.3"  # Error.
# t2.sh: let: b = 1.5 + 1.3: syntax error in expression (error token is ".5 + 1.3")

echo "b = $b"       # b=1
Use bc in scripts that that need floating point calculations or math library functions.

[Jun 19, 2008] Bash Arrays by Mitch Frazier

Jun, 2008 | Linux Journal

If you're used to a "standard" *NIX shell you may not be familiar with bash's array feature. Although not as powerful as similar constructs in the P languages (Perl, Python, and PHP) and others, they are often quite useful.

Bash arrays have numbered indexes only, but they are sparse, ie you don't have to define all the indexes. An entire array can be assigned by enclosing the array items in parenthesis:

  arr=(Hello World)
Individual items can be assigned with the familiar array syntax (unless you're used to Basic or Fortran):
  arr[0]=Hello
  arr[1]=World
But it gets a bit ugly when you want to refer to an array item:
  echo ${arr[0]} ${arr[1]}
To quote from the man page:
The braces are required to avoid conflicts with pathname expansion.

In addition the following funky constructs are available:

  ${arr[*]}         # All of the items in the array
  ${!arr[*]}        # All of the indexes in the array
  ${#arr[*]}        # Number of items in the array
  ${#arr[0]}        # Length if item zero
The ${!arr[*]} is a relatively new addition to bash, it was not part of the original array implementation.

The following example shows some simple array usage (note the "[index]=value" assignment to assign a specific index):

#!/bin/bash

array=(one two three four [5]=five)

echo "Array size: ${#array[*]}"

echo "Array items:"
for item in ${array[*]}
do
    printf "   %s\n" $item
done

echo "Array indexes:"
for index in ${!array[*]}
do
    printf "   %d\n" $index
done

echo "Array items and indexes:"
for index in ${!array[*]}
do
    printf "%4d: %s\n" $index ${array[$index]}
done
Running it produces the following output:
Array size: 5
Array items:
   one
   two
   three
   four
   five
Array indexes:
   0
   1
   2
   3
   5
Array items and indexes:
   0: one
   1: two
   2: three
   3: four
   5: five

Note that the "@" sign can be used instead of the "*" in constructs such as ${arr[*]}, the result is the same except when expanding to the items of the array within a quoted string. In this case the behavior is the same as when expanding "$*" and "$@" within quoted strings: "${arr[*]}" returns all the items as a single word, whereas "${arr[@]}" returns each item as a separate word.

The following example shows how unquoted, quoted "*", and quoted "@" affect the expansion (particularly important when the array items themselves contain spaces):

#!/bin/bash

array=("first item" "second item" "third" "item")

echo "Number of items in original array: ${#array[*]}"
for ix in ${!array[*]}
do
    printf "   %s\n" "${array[$ix]}"
done
echo

arr=(${array[*]})
echo "After unquoted expansion: ${#arr[*]}"
for ix in ${!arr[*]}
do
    printf "   %s\n" "${arr[$ix]}"
done
echo

arr=("${array[*]}")
echo "After * quoted expansion: ${#arr[*]}"
for ix in ${!arr[*]}
do
    printf "   %s\n" "${arr[$ix]}"
done
echo

arr=("${array[@]}")
echo "After @ quoted expansion: ${#arr[*]}"
for ix in ${!arr[*]}
do
    printf "   %s\n" "${arr[$ix]}"
done
When run it outputs:
Number of items in original array: 4
   first item
   second item
   third
   item

After unquoted expansion: 6
   first
   item
   second
   item
   third
   item

After * quoted expansion: 1
   first item second item third item

After @ quoted expansion: 4
   first item
   second item
   third
   item

Mitch Frazier is the System Administrator at Linux Journal.

Arithmetic expansion with double parentheses, and using let

The use of backticks (backquotes) in arithmetic expansion has been superseded by double parentheses -- ((...)) and $((...)) -- and also by the very convenient let construction.
z=$(($z+3))
z=$((z+3))                                  #  Also correct.
                                            #  Within double parentheses,
                                            #+ parameter dereferencing
                                            #+ is optional.

# $((EXPRESSION)) is arithmetic expansion.  #  Not to be confused with
                                            #+ command substitution.



# You may also use operations within double parentheses without assignment.

  n=0
  echo "n = $n"                             # n = 0

  (( n += 1 ))                              # Increment.
# (( $n += 1 )) is incorrect!
  echo "n = $n"                             # n = 1


let z=z+3
let "z += 3"  #  Quotes permit the use of spaces in variable assignment.
              #  The 'let' operator actually performs arithmetic evaluation,
              #+ rather than expansion.

Recommended Links

Softpanorama Top Visited

Softpanorama Recommended

Please visit  Heiner Steven SHELLdorado  the best shell scripting site on the Internet

Advanced Bash-Scripting Guide

Bash Arrays  by Mitch Frazier (Linux Journal, 2008)

Linux.com Turn Vim into a bash IDE

Debugging

Linux tip Bash test and comparison functions

Common shell script mistakes

Reference

Examples shipped with bash 3.2 and newer
Path Description X-ref
./bashdb 
Deprecated sample implementation of a bash debugger.  
./complete 
Shell completion code.  
./functions 
Example functions.  
./functions/array-stuff 
Various array functions (ashift, array_sort, reverse).  
./functions/array-to-string 
Convert an array to a string.  
./functions/autoload 
An almost ksh-compatible 'autoload' (no lazy load). ksh
./functions/autoload.v2 
An almost ksh-compatible 'autoload' (no lazy load). ksh
./functions/autoload.v3 
A more ksh-compatible 'autoload' (with lazy load). ksh
./functions/basename 
A replacement for basename(1). basename
./functions/basename2 
Fast basename(1) and dirname(1) functions for bash/sh. basename, dirname
./functions/coproc.bash 
Start, control, and end co-processes.  
./functions/coshell.bash 
Control shell co-processes (see coprocess.bash).  
./functions/coshell.README 
README for coshell and coproc.  
./functions/csh-compat 
A C-shell compatibility package. csh
./functions/dirfuncs 
Directory manipulation functions from the book The Korn Shell.  
./functions/dirname 
A replacement for dirname(1). dirname
./functions/emptydir 
Find out if a directory is empty.  
./functions/exitstat 
Display the exit status of processes.  
./functions/external 
Like command, but forces the use of external command.  
./functions/fact 
Recursive factorial function.  
./functions/fstty 
Front-end to sync TERM changes to both stty(1) and readline 'bind'. stty.bash
./functions/func 
Print out definitions for functions named by arguments.  
./functions/gethtml 
Get a web page from a remote server (wget(1) in bash).  
./functions/getoptx.bash 
getopt function that parses long-named options.  
./functions/inetaddr 
Internet address conversion (inet2hex and hex2inet).  
./functions/inpath 
Return zero if the argument is in the path and executable. inpath
./functions/isnum.bash 
Test user input on numeric or character value.  
./functions/isnum2 
Test user input on numeric values, with floating point.  
./functions/isvalidip 
Test user input for valid IP addresses.  
./functions/jdate.bash 
Julian date conversion.  
./functions/jj.bash 
Look for running jobs.  
./functions/keep 
Try to keep some programs in the foreground and running.  
./functions/ksh-cd 
ksh-like cd: cd [-LP] [dir[change]]. ksh
./functions/ksh-compat-test 
ksh-like arithmetic test replacements. ksh
./functions/kshenv 
Functions and aliases to provide the beginnings of a ksh environment for bash ksh
./functions/login 
Replace the login and newgrp built-ins in old Bourne shells.  
./functions/lowercase 
Rename files to lowercase. rename lower
./functions/manpage 
Find and print a manpage. fman
./functions/mhfold 
Print MH folders, useful only because folders(1) doesn't print mod date/times.  
./functions/notify.bash 
Notify when jobs change status.  
./functions/pathfuncs 
Path related functions (no_path, add_path, pre-path, del_path). path
./functions/README 
README  
./functions/recurse 
Recursive directory traverser.  
./functions/repeat2 
A clone of the C shell built-in repeat. repeat, csh
./functions/repeat3 
A clone of the C shell built-in repeat. repeat, csh
./functions/seq 
Generate a sequence from m to n;m defaults to 1.  
./functions/seq2 
Generate a sequence from m to n;m defaults to 1.  
./functions/shcat 
Readline-based pager. cat, readline pager
./functions/shcat2 
Readline-based pagers. cat, readline pager
./functions/sort-pos-params 
Sort the positional parameters.  
./functions/substr 
A function to emulate the ancient ksh built-in. ksh
./functions/substr2 
A function to emulate the ancient ksh built-in. ksh
./functions/term 
A shell function to set the terminal type interactively or not.  
./functions/whatis 
An implementation of the 10th Edition Unix sh built-in whatis(1) command.  
./functions/whence 
An almost ksh-compatible whence(1) command.  
./functions/which 
An emulation of which(1) as it appears in FreeBSD.  
./functions/xalias.bash 
Convert csh alias commands to bash functions. csh, aliasconv
./functions/xfind.bash 
A find(1) clone.  
./loadables/ 
Example loadable replacements.  
./loadables/basename.c 
Return nondirectory portion of pathname. basename
./loadables/cat.c 
cat(1) replacement with no options—the way cat was intended. cat, readline pager
./loadables/cut.c 
cut(1) replacement.  
./loadables/dirname.c 
Return directory portion of pathname. dirname
./loadables/finfo.c 
Print file info.  
./loadables/getconf.c 
POSIX.2 getconf utility.
./loadables/getconf.h 
Replacement definitions for ones the system doesn't provide.  
./loadables/head.c 
Copy first part of files.  
./loadables/hello.c 
Obligatory "Hello World" / sample loadable.  
./loadables/id.c 
POSIX.2 user identity.  
./loadables/ln.c 
Make links.  
./loadables/logname.c 
Print login name of current user.  
./loadables/Makefile.in 
Simple makefile for the sample loadable built-ins.  
./loadables/mkdir.c 
Make directories.  
./loadables/necho.c 
echo without options or argument interpretation.  
./loadables/pathchk.c 
Check pathnames for validity and portability.  
./loadables/print.c 
Loadable ksh-93 style print built-in.  
./loadables/printenv.c 
Minimal built-in clone of BSD printenv(1).  
./loadables/push.c 
Anyone remember TOPS-20?  
./loadables/README 
README  
./loadables/realpath.c 
Canonicalize pathnames, resolving symlinks.  
./loadables/rmdir.c 
Remove directory.  
./loadables/sleep.c 
Sleep for fractions of a second.  
./loadables/strftime.c 
Loadable built-in interface to strftime(3).  
./loadables/sync.c 
Sync the disks by forcing pending filesystem writes to complete.  
./loadables/tee.c 
Duplicate standard input.  
./loadables/template.c 
Example template for loadable built-in.  
./loadables/truefalse.c 
True and false built-ins.  
./loadables/tty.c 
Return terminal name.  
./loadables/uname.c 
Print system information.  
./loadables/unlink.c 
Remove a directory entry.  
./loadables/whoami.c 
Print out username of current user.  
./loadables/perl/ 
Illustrates how to build a Perl interpreter into bash.  
./misc 
Miscellaneous  
./misc/aliasconv.bash 
Convert csh aliases to bash aliases and functions. csh, xalias
./misc/aliasconv.sh 
Convert csh aliases to bash aliases and functions. csh, xalias
./misc/cshtobash 
Convert csh aliases, environment variables, and variables to bash equivalents. csh, xalias
./misc/README 
README  
./misc/suncmd.termcap 
SunView TERMCAP string.  
./obashdb 
Modified version of the Korn Shell debugger from Bill Rosenblatt's Learning the Korn Shell.
./scripts.noah 
Noah Friedman's collection of scripts (updated to bash v2 syntax by Chet Ramey).  
./scripts.noah/aref.bash 
Pseudo-arrays and substring indexing examples.  
./scripts.noah/bash.sub.bash 
Library functions used by require.bash.  
./scripts.noah/bash_version. bash 
A function to slice up $BASH_VERSION.  
./scripts.noah/meta.bash 
Enable and disable eight-bit readline input.  
./scripts.noah/mktmp.bash 
Make a temporary file with a unique name.  
./scripts.noah/number.bash 
A fun hack to translate numerals into English.  
./scripts.noah/PERMISSION 
Permissions to use the scripts in this directory.  
./scripts.noah/prompt.bash 
A way to set PS1 to some predefined strings.  
./scripts.noah/README 
README  
./scripts.noah/remap_keys.bash 
A front end to bind to redo readline bindings. readline
./scripts.noah/require.bash 
Lisp-like require/provide library functions for bash.  
./scripts.noah/send_mail. 
Replacement SMTP client written in bash.  
./scripts.noah/shcat.bash 
bash replacement for cat(1). cat
./scripts.noah/source.bash 
Replacement for source that uses current directory.  
./scripts.noah/string.bash 
The string(3) functions at the shell level.  
./scripts.noah/stty.bash 
Front-end to stty(1) that changes readline bindings too. fstty
./scripts.noah/y_or_n_p.bash 
Prompt for a yes/no/quit answer. ask
./scripts.v2 
John DuBois' ksh script collection (converted to bash v2 syntax by Chet Ramey).  
./scripts.v2/arc2tarz 
Convert an arc archive to a compressed tar archive.  
./scripts.v2/bashrand 
Random number generator with upper and lower bounds and optional seed. random
./scripts.v2/cal2day.bash 
Convert a day number to a name.  
./scripts.v2/cdhist.bash 
cd replacement with a directory stack added.  
./scripts.v2/corename 
Tell what produced a core file.  
./scripts.v2/fman 
Fast man(1) replacement. manpage
./scripts.v2/frcp 
Copy files using ftp(1) but with rcp-type command-line syntax.  
./scripts.v2/lowercase 
Change filenames to lowercase. rename lower
./scripts.v2/ncp 
A nicer front end for cp(1) (has -i, etc)..  
./scripts.v2/newext 
Change the extension of a group of files. rename
./scripts.v2/nmv 
A nicer front end for mv(1) (has -i, etc).. rename
./scripts.v2/pages 
Print specified pages from files.  
./scripts.v2/PERMISSION 
Permissions to use the scripts in this directory.  
./scripts.v2/pf 
A pager front end that handles compressed files.  
./scripts.v2/pmtop 
Poor man's top(1) for SunOS 4.x and BSD/OS.  
./scripts.v2/README 
README  
./scripts.v2/ren 
Rename files by changing parts of filenames that match a pattern. rename
./scripts.v2/rename 
Change the names of files that match a pattern. rename
./scripts.v2/repeat 
Execute a command multiple times. repeat
./scripts.v2/shprof 
Line profiler for bash scripts.  
./scripts.v2/untar 
Unarchive a (possibly compressed) tarfile into a directory.  
./scripts.v2/uudec 
Carefully uudecode(1) multiple files.  
./scripts.v2/uuenc 
uuencode(1) multiple files.  
./scripts.v2/vtree 
Print a visual display of a directory tree. tree
./scripts.v2/where 
Show where commands that match a pattern are.  
./scripts 
Example scripts.  
./scripts/adventure.sh 
Text adventure game in bash!  
./scripts/bcsh.sh 
Bourne shell's C shell emulator. csh
./scripts/cat.sh 
Readline-based pager. cat, readline pager
./scripts/center 
Center a group of lines.  
./scripts/dd-ex.sh 
Line editor using only /bin/sh, /bin/dd, and /bin/rm.  
./scripts/fixfiles.bash 
Recurse a tree and fix files containing various bad characters.  
./scripts/hanoi.bash 
The inevitable Towers of Hanoi in bash.  
./scripts/inpath 
Search $PATH for a file the same name as $1; return TRUE if found. inpath
./scripts/krand.bash 
Produces a random number within integer limits. random
./scripts/line-input.bash 
Line input routine for GNU Bourne Again Shell plus terminal-control primitives.  
./scripts/nohup.bash 
bash version of nohup command.  
./scripts/precedence 
Test relative precedences for && and || operators.  
./scripts/randomcard.bash 
Print a random card from a card deck. random
./scripts/README 
README  
./scripts/scrollbar 
Display scrolling text.  
./scripts/scrollbar2 
Display scrolling text.  
./scripts/self-repro 
A self-reproducing script (careful!).  
./scripts/showperm.bash 
Convert ls(1) symbolic permissions into octal mode.  
./scripts/shprompt 
Display a prompt and get an answer satisfying certain criteria. ask
./scripts/spin.bash 
Display a spinning wheel to show progress.  
./scripts/timeout 
Give rsh(1) a shorter timeout.  
./scripts/vtree2 
Display a tree printout of the direcotry with disk use in 1k blocks. tree
./scripts/vtree3 
Display a graphical tree printout of dir. tree
./scripts/vtree3a 
Display a graphical tree printout of dir. tree
./scripts/websrv.sh 
A web server in bash!  
./scripts/xterm_title 
Print the contents of the xterm title bar.  
./scripts/zprintf 
Emulate printf (obsolete since printf is now a bash built-in).  
./startup-files 
Example startup files.  
./startup-files/Bash_aliases 
Some useful aliases (written by Fox).  
./startup-files/Bash_profile 
Sample startup file for bash login shells (written by Fox).  
./startup-files/bash-profile 
Sample startup file for bash login shells (written by Ramey).  
./startup-files/bashrc 
Sample Bourne Again Shell init file (written by Ramey).  
./startup-files/Bashrc.bfox 
Sample Bourne Again Shell init file (written by Fox).  
./startup-files/README 
README  
./startup-files/apple 
Example startup files for Mac OS X.  
./startup-files/apple/aliases 
Sample aliases for Mac OS X.  
./startup-files/apple/bash.defaults 
Sample User preferences file.  
./startup-files/apple/environment 
Sample Bourne Again Shell environment file.  
./startup-files/apple/login 
Sample login wrapper.  
./startup-files/apple/logout 
Sample logout wrapper.  
./startup-files/apple/rc 
Sample Bourne Again Shell config file.  
./startup-files/apple/README 
README



Etc

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available in our efforts to advance understanding of environmental, political, human rights, economic, democracy, scientific, and social justice issues, etc. We believe this constitutes a 'fair use' of any such copyrighted material as provided for in section 107 of the US Copyright Law. In accordance with Title 17 U.S.C. Section 107, the material on this site is distributed without profit exclusivly for research and educational purposes.   If you wish to use copyrighted material from this site for purposes of your own that go beyond 'fair use', you must obtain permission from the copyright owner. 

ABUSE: IPs or network segments from which we detect a stream of probes might be blocked for no less then 90 days. Multiple types of probes increase this period.  

Society

Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers :   Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism  : The Iron Law of Oligarchy : Libertarian Philosophy

Quotes

War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda  : SE quotes : Language Design and Programming Quotes : Random IT-related quotesSomerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose BierceBernard Shaw : Mark Twain Quotes

Bulletin:

Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 :  Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method  : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law

History:

Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds  : Larry Wall  : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOSProgramming Languages History : PL/1 : Simula 67 : C : History of GCC developmentScripting Languages : Perl history   : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history

Classic books:

The Peter Principle : Parkinson Law : 1984 : The Mythical Man-MonthHow to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite

Most popular humor pages:

Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor

The Last but not Least


Copyright © 1996-2015 by Dr. Nikolai Bezroukov. www.softpanorama.org was created as a service to the UN Sustainable Development Networking Programme (SDNP) in the author free time. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License.

The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to make a contribution, supporting development of this site and speed up access. In case softpanorama.org is down currently there are two functional mirrors: softpanorama.info (the fastest) and softpanorama.net.

Disclaimer:

The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the author present and former employers, SDNP or any other organization the author may be associated with. We do not warrant the correctness of the information provided or its fitness for any purpose.

Last modified: June, 01, 2015