Skip to content

Bash Tips

Printf

printf "%s\n" print arguments on "separate lines"
print
arguments
on
separate
lines
printf "%b\n" "Hello\nWorld" "12\twords"
Hello
World
12      words
printf "%d\n" 23 45 56.78 0xff 011
23
45
-bash: printf: 56.78: invalid number
56
255
9

Note

Using a leading 0 is going to be octal. Using a lead 0x is going to be hexadecimal.

printf "%f\n" 12.24 23 56.789 1.2345678
12.240000
23.000000
56.789000
1.234568
printf "%e\n" 12.34 23
1.234000e+01
2.300000e+01

Width

Note

- here in output means space.

printf "%8s %10s\n" nima saed
----nima ------saed
printf "%8s %-10s\n" nima saed
----nima saed------
printf "%8.2s %-10s\n" nima saed
------ni saed------
printf "%4d\n" 23 54
--23
--54
printf "%04d\n" 23 54
0023
0054
printf "%10.4d\n" 23 54
------0023
------0054
printf "%10.4f\n" 23 54
---23.0000
---54.0000

read command

read a b "test test1 test2"

echo $a
echo $b
test
test1 test2

while loop

while
    command lists
do
    command lists
done

examples

while
    ((x<10))
do
    echo loop $x;
    date > date.$x;
    ((x=x+1))
done
while
    read a b
do
    echo a is $a b is $b
done <data_file
ls -l | while read a b c d; do echo owner is $c; done

For Loops

for <var> in <list>
do
    comand lists
done

Examples

for i in dog cat elephant
do
    echo i is $i
done
for i in dog cat elephant; do echo i is $i; done

seq

seq 1 5
1
2
3
4
5
for num in `seq 1 5`; do echo $num; done
1
2
3
4
5

Note

You can also use {A..Z}, {a..f} or {1..10} in for loops.

for i in {a..f}; do echo $i; done
a
b
c
d
e
f

Dealing with files

for d in $(<data_file); do echo $d; done
for j in *.c
# making a list with file globbing
do
    command
done
for f in $(find . -name *.c)
do
 command
done

List/Array

for n in ${list[@]}; do echo $n; done

Functions

function name{
    command list
}
function myfunc {
    echo starting
    return
    echo this will not be executed
}

Export functions

export -f myfunc

Case Statement

case expression in
pattern 1 )
    command list ;;
pattern 2 )
    command list ;;
esac
case $ans in
yes|YES|y|Y|y.x) echo "Will do!";;
n*|N*) echo "Will NOT do!";;
*) echo "Oops!";;
esac

If-Then-Else Statement

if
    command list # last result is used
    then
    command list
    [else
    command list]
fi

Example

if
grep -q important myfile
then
    echo myfile has important stuff
else
    echo myfile does not have important stuff
fi

Extra

File name and path

Note

This code is inside the script file.

To get name of script file

echo $0

To get full path of the file

echo $(readlink -f $0)

To get full path but move one directory up

echo $(dirname "$(readlink -f $0)")

Progress bar

echo -ne '#####                     (33%)\r'
sleep 1
echo -ne '#############             (66%)\r'
sleep 1
echo -ne '#######################   (100%)\r'
echo -ne '\n'

Bash parsing and expansion

  1. Brace expansion
{one,two,three}
{1..10} or {a..z}
pre{d,l}ate
{{1..3},{a..c}} => 1,2,3,a,b,c
{1..3}{a..c} => 1a,1b,1c,2a,...,3c
{01..13..3} => 01,04,07,10,13
{a..h..3} => a,d,g
  1. Tilde expansion
~ => /home/nima
~someone => /home/someone
~noUser => ~noUser
  1. Parameter and variable expansion
var=whatever
$var or ${var} => whatever
echo $var $var #are having different result  if there are white spaces
  1. Arithmetic expansion
$(( expression ))
  1. Command substitution
wc -l $( date +%Y-%m-%d).log

Note

If command substitution is not quoted, word splitting and pathname expansion are performed on the result.

  1. Word splitting

The result of parameter and arithmetic expansion, as well as command substitution, are subject to word splitting if the were NOT QUETED

var="this is a multi-word value"
printf ":%s:\n" $var
:this:
:is:
:a:
:multi-word:
:value:
var="this is a multi-word value"
printf ":%s:\n" $var
:this is a multi-word value:

Note

Word splitting is based on value of IFS (Internal Field Separator). IFS default value is space, tab, and newline. (IFS=$' \t\n'). You can change IFS value to any value.

  1. Pathname expansion

Char in use are *, ?, and []

echo D*

list files starting with capital D.

echo ?a*

list files which the second char is a.

echo *[0-9]*

list files which there is at least one number in there name.

  1. Process substitution
<(command)
>(command)

Parameter Expansion

empty or unset variable

  1. Default

    • echo {var:-default} => default if it is not set and empty string
    • echo {var-default} => default if it is not set
  2. Alternative

    • echo {var:+alter} => alter if it is set and not empty string
    • echo {var+alter} => alter if it is set
  3. Default with assignment

    • echo {var:=default} => default if it is not set and empty string, assign default to var as well
    • echo {var=default} => default if it is not set, assign default to var as well.
  4. Message

    • echo {var:?message} => display error message if it is not set and empty string
    • echo {var?message} => display error message if it is not set

** Length of var

var=test
echo ${#var}
4

Remove Pattern

  • Short from end

var=Toronto
echo ${var%o*}
Toront

  • Long from end
var=Toronto
echo ${var%%o*}
T
  • Short from beginning
var=Toronto
echo ${var#*o}
ronto
  • Long from beginning
scriptname=${0##*/} ## /home/user/script.sh => script.sh

Replace pattern

password=reretrgfdsgdhdt
echo "${password//?/*}"
*************

Substring var:offset:length

var=Toronto
echo "${var:3:2}"
on
var=Toronto
echo "${var:1}"
oronto

Negative offset

var=Toronto
echo "${var: -3}" # Do not forget about space betwen : and -
nto