Bash Index : B - The 'B' Bash commands : description, flags and examples

mail

bg

bg jobSpec
mail

base64

Usage

Encode / decode strings (or files) into / from base64 format.
Once base64-encoded, some file types have recognizable "signatures" (i.e. the base64 strings start with the same characters, source, related) :
PNG files
iVBORw0KGgo
JPG files
/9j

Flags

Flag Usage
(none) encode parameter into base64 format
-d base64EncodedString
--decode base64EncodedString
decode base64EncodedString
-w n
--wrap=n
wrap encoded lines after n characters (defaults to 76).
Use 0 to disable line wrapping (i.e. output a giant single line)

Example

Encode data into base64 :

  • manually :
    1. base64 -
    2. Hello World ! If you press now, it'll be appended to the string to encode.
    3. CTRL-d-d
    4. The encoded string will be displayed right after the input string : SGVsbG8gV29ybGQgIQ==
  • echo -n 'Hello World !' | base64
Both return SGVsbG8gV29ybGQgIQ==.

Some documentations also mention the herestring syntax —which works fine— but appends a newline to the expression to encode (like echo does) :
expression='Hello World !'; echo "$expression" | base64; base64 <<< "$expression"
SGVsbG8gV29ybGQgIQo=
SGVsbG8gV29ybGQgIQo=

Decode a base64 string :

  • echo -n 'Hello World !' | base64 | base64 -d
    Hello World !
  • echo 'Ik5ldmVyIHRydXN0IGEgY29tcHV0ZXIgeW91IGNhbid0IHRocm93IG91dCBhIHdpbmRvdyIgLSBTdGV2ZSBXb3puaWFr' | base64 -d
  • echo 'Ik5ldmVyIHRydXN0IGEgY29tcHV0ZXIgeW91IGNhbid0IHRocm93IG91dCBhIHdpbmRvdyIgLSBTdGV2ZSBXb3puaWFr' | openssl enc -d -base64
mail

basename

basename file
return the file name without its path
basename file string
same as above + remove string from the end of the file name. This can be used to remove a known file extension.
mail

bc

Usage

bc is a calculator that can be used either
There's a common misconception about the -l flag and its necessity in floating point divisions :
  • -l is actually not necessary if you set the scale yourself
  • if you use neither -l nor scale in a division, you'll only get the integer part of the result. The displayed result is NOT :
    • a round() of the result
    • a modulo ...
Examples :
  • echo '1/2' | $(which bc); echo '1/2' | $(which bc) -l; echo 'scale=2; 1/2' | $(which bc)
    0			integer part only
    .50000000000000000000	20 decimals, as expected 
    .50			only 2 decimals, as specified
  • for i in {8..16}; do echo -n "$i / 3 = "; echo $i/3 | $(which bc); done
    8 / 3 = 2
    9 / 3 = 3
    10 / 3 = 3
    11 / 3 = 3
    12 / 3 = 4
    13 / 3 = 4
    14 / 3 = 4
    15 / 3 = 5
    16 / 3 = 5
  • You may trick the result by hacking the order of the operations :
    echo '1/2*2' | $(which bc); echo '2*1/2' | $(which bc)
    0	1 / 2 = 0.5 → 0, 0 * 2 = 0.0 → 0
    1	2 * 1 = 2.0 → 2, 2 / 2 = 1.0 → 1

Flags

Flag Usage
-l --mathlib
  1. preload a math library
  2. set the scale to 20
-q --quiet do not print the welcome banner

Special variables

details : man -P 'less -p "four special variables"' bc
Name Usage
scale=n set the number of digits after the decimal point to n
echo 'scale=3; 1+1; 1/1' | bc
2
1.000
defaults to 0.

Example

Some basic examples :

echo '1+1' | bc
2
echo '331507551852/1024/1024/1024' | bc
308

How to round float numbers into integers (source, see also) ?

echo '(3.141592654+0.5)/1' | bc
3
echo '(2.71828+0.5)/1' | bc
3
printf %0.f 3.141592654
3
printf %0.f 3.1 3.5 3.9
344
number=3.333; multiplier=3; echo $(printf %0.f $(echo "$number*$multiplier" | bc))
10
Trying to round numbers with printf :

for i in 0.5 1.5 2.5 3.5 4.5 5.5 6.5 7.5 8.5 9.5; do printf "i : %s, round(i,0) : %.0f\n" "$i" "$i"; done | column -t
i  :  0.5,  round(i,0)  :  0		can't explain this
i  :  1.5,  round(i,0)  :  2		can't explain this
i  :  2.5,  round(i,0)  :  2
i  :  3.5,  round(i,0)  :  4
i  :  4.5,  round(i,0)  :  4
i  :  5.5,  round(i,0)  :  6
i  :  6.5,  round(i,0)  :  6
i  :  7.5,  round(i,0)  :  8
i  :  8.5,  round(i,0)  :  8
i  :  9.5,  round(i,0)  :  10
for i in 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1; do printf "i : %s, round(i,1) : %.1f, round(i,0) : %.0f\n" "$i" "$i" "$i"; done | column -t
i  :  0,    round(i,1)  :  0.0,  round(i,0)  :  0
i  :  0.1,  round(i,1)  :  0.1,  round(i,0)  :  0
i  :  0.2,  round(i,1)  :  0.2,  round(i,0)  :  0
i  :  0.3,  round(i,1)  :  0.3,  round(i,0)  :  0
i  :  0.4,  round(i,1)  :  0.4,  round(i,0)  :  0
i  :  0.5,  round(i,1)  :  0.5,  round(i,0)  :  0	not rounded to 1 
i  :  0.6,  round(i,1)  :  0.6,  round(i,0)  :  1
i  :  0.7,  round(i,1)  :  0.7,  round(i,0)  :  1
i  :  0.8,  round(i,1)  :  0.8,  round(i,0)  :  1
i  :  0.9,  round(i,1)  :  0.9,  round(i,0)  :  1
i  :  1,    round(i,1)  :  1.0,  round(i,0)  :  1
for i in 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1; do simple=$(echo "$i/1" | bc); rounded=$(echo "($i+0.5)/1" | /usr/bin/bc); echo "$i $simple $rounded"; done | column -t
0    0                       0
0.1  .10000000000000000000   0
0.2  .20000000000000000000   0
0.3  .30000000000000000000   0
0.4  .40000000000000000000   0
0.5  .50000000000000000000   1	now rounded to 1 
0.6  .60000000000000000000   1
0.7  .70000000000000000000   1
0.8  .80000000000000000000   1
0.9  .90000000000000000000   1
1    1.00000000000000000000  1
var=2.5; echo $var | awk '{print int($1+0.5)}' 3
for i in {1000..1005}; do a=$(echo "$i/2" | /usr/bin/bc); b=$(echo "scale=1; $i/2" | /usr/bin/bc); c=$(echo "scale=1; (($i/2)+0.5)/1" | /usr/bin/bc); echo -e "$i/2=\t$a\t$b\t$c"; done
1000/2= 500     500.0   500.5
1001/2= 500     500.5   501.0
1002/2= 501     501.0   501.5
1003/2= 501     501.5   502.0
1004/2= 502     502.0   502.5
1005/2= 502     502.5   503.0
==> so far, I've found no "pure-bc" means to round to integer

How to convert numbers between HEX, BIN and DEC (source) ?

To do so, use the ibase (input base) and obase (output base) bc options :

echo 'ibase=16; FF' | bc Hexadecimal letters must be written uppercase.
255
echo 'obase=16; 255 | bc
FF
echo 'ibase=10; obase=2; 73' | bc
1001001
mail

break

Usage

break n exits from the smallest enclosing for, while, or until loop, or from the nth enclosing loop, if n is specified (defaults to 1).

Example

Basic example : interrupting a single for loop :

#!/usr/bin/env bash

for i in {1..2}; do
	echo $i
	break
	echo 'this will never be executed'
done
displays :
1

2 nested for loops :

#!/usr/bin/env bash

for i in {1..2}; do
	for j in {a..b}; do
		echo $i$j
		break
		echo 'this will never be executed'
	done
done
displays :
1a
2a

2 nested for loops and break 2 :

#!/usr/bin/env bash

for i in {1..2}; do
	for j in {a..b}; do
		echo $i$j
		break 2
		echo 'this will never be executed'
	done
done
displays :
1a
mail

bzip2

Usage

Compress data

You definitely should have a look at pbzip2 :

  1. apt-get install pbzip2
  2. Create aliases :
    alias bzip2='pbzip2'
    alias bunzip2='pbzip2 -d'

bzip2 default behavior

  • the input files are deleted after compressing / decompressing. Change this this -k
  • the compressed file has the same date+time than the original file :
    testFile='/tmp/testFile'; touch -d 'now -1234567890 seconds' "$testFile"; echo BEFORE; ls -l "$testFile"; bzip2 "$testFile"; echo AFTER; ls -l "$testFile"*; rm "$testFile.bz2"; type bzip2
    BEFORE
    -rw------- 1 bob users 0  May 23  1982 /tmp/testFile		both files have the same date
    AFTER
    -rw------- 1 bob users 14 May 23  1982 /tmp/testFile.bz2
    bzip2 is aliased to `pbzip2'						we used pbzip2, which mimics bzip2 behavior

Flags

Flag Usage
  • -1 --fast
  • -9 --best (default)
short version :
compression ratio, ignored for decompression
detailed version :
  • block size used during compression, which affects compression ratio and memory usage (both for compression and decompression)
  • this value is saved in the compressed file header and re-used for decompression, which is why the parameter is ignored for decompression
  • compression and decompression speed are virtually unaffected by block size
  • unless in some very specific situation, the default value -9 applies to most cases
-k --keep keep input files during compression or decompression