Practical Bash Commmands

Intro

There are different kinds of shells:

  • Bourne Shell(/usr/bin/sh or /bin/sh
  • Bourne Again Shell(/bin/bash
  • C Shell(/usr/bin/csh
  • K Shell(/usr/bin/ksh
  • Shell for Root(/sbin/sh

But in this blog, we will basically focus on bash.

Basics

Hello World!

#!/bin/bash
echo "Hello World!"

Permission

chmod +x ./test.sh  # gives permission to this bash script

Run

# the following command need permission
./test.sh
# the following two methods doesn't need permission
sh test.sh  # this method lead to the usage of dash instead of bash
            # so problems might happen
bash test.sh

Variables

Fundamentals

  1 #!/bin/bash
  2 echo "======================================================="
  3 echo ">> Preparing to print out the files at /home/yzy/Downloads"
  4 for file in `ls /home/yzy/Downloads`; do
  5   echo "There are files called ${file} at /home/yzy/Downloads/"
  6 done
  7 echo "======================================================="
  8 echo ">> Preparing to pring out my skills"
  9 for skill in Ada Coffe Action Java; do
 10   echo "I am good at ${skill}Script"
 11 done
 12 echo "======================================================="
 13 echo ">> Reset variables"
 14 your_name="tom"
 15 echo $your_name
 16 your_name="Juillet"
 17 echo $your_name
 18 echo "======================================================="
 19 echo ">> Play with read-only variable"
 20 myUrl="https://www.zhiyuanyao.com"
 21 readonly myUrl
 22 # You are not able to change the variable here
 23 # myUrl="http://www.w3cschool.cc"
 24 echo "======================================================="
 25 echo ">> Playing with unset"
 26 myVar="Hello!"
 27 unset myVar
 28 echo $myVar
 29 # You will not see anything here

String

  1 #!/bin/bash
  2 echo "======================================================="
  3 echo ">> Greeting"
  4 your_name='ZhiyuanYaoJ'
  5 greeting="Hello, I know your are \"$your_name\"!"
  6 greeting_1="Hello, "$your_name"!"
  7 greeting_2="Hello, ${your_name}!"
  8 echo ${greeting} ${greeting_1} ${greeting_2}
  9 printf "${greeting}\n${greeting_1}\n${greeting_2}\n"
 10 echo "======================================================="
 11 echo ">> Length of string"
 12 echo "Length of your_name = ${#your_name}"
 13 echo "======================================================="
 14 echo ">> Substring"
 15 var="http://www.aaa.com/123.htm"
 16 echo "原始 String:"
 17 echo "  var = \""${var}"\""
 18 printf "从左边开始删除第一个'//'及左边的所有字符:\n  var#*// = \""${var#*//}"\"\n"
 19 printf "从右边开始删除第一个'/'及左边的所有字符:\n  var##*/ = \""${var##*/}"\"\n"
 20 echo "从右边开始删除第一个'/'及右边的所有字符:"
 21 echo "  var%/* = \""${var%/*}"\""
 22 printf "从右边开始删除最后一个'/'及右边的字符:\n  var%%/* = \""${var%%/*}"\"\n"
 23 printf "从左边第 1 个字符开始截取 5 个字符:\n  var:0:5 = \""${var:0:5}"\"\n"
 24 printf "查找子字符串 \'1\'\'m\' 的位置(优先输出靠左的字符位置):\n  "`expr index "${var}" 1m`"\n"
 25 echo "======================================================="

Outcome:

=======================================================
>> Greeting
Hello, I know your are "ZhiyuanYaoJ"! Hello, ZhiyuanYaoJ! Hello, ZhiyuanYaoJ!
Hello, I know your are "ZhiyuanYaoJ"!
Hello, ZhiyuanYaoJ!
Hello, ZhiyuanYaoJ!
=======================================================
>> Length of string
Length of your_name = 11
=======================================================
>> Substring
原始 String:
  var = "http://www.aaa.com/123.htm"
从左边开始删除第一个'//'及左边的所有字符:
  var#*// = "www.aaa.com/123.htm"
从右边开始删除第一个'/'及左边的所有字符:
  var##*/ = "123.htm"
从右边开始删除第一个'/'及右边的所有字符:
  var%/* = "http://www.aaa.com"
从右边开始删除最后一个'/'及右边的字符:
  var%/* = "http:"
从左边第 1 个字符开始截取 5 个字符:
  var:0:5 = "http:"
查找子字符串 '1''m' 的位置(优先输出靠左的字符位置):
  18
=======================================================

Array

Operations

  1 #!/bin/bash
  2
  3 arr=(
  4   1
  5   1
  6   2
  7   3
  8   5
  9   8
 10   13
 11 )
 12
 13 # get all elements
 14 echo "Initialized arr: "${arr[*]}
 15
 16 # define specific element
 17 echo "Mess a bit with arr..."
 18 echo "set: arr[0]=13"
 19 echo "set: arr[20]=20"
 20 arr[0]=13
 21 arr[20]=20
 22
 23 # get an element
 24 tmp=${arr[19]}
 25
 26 echo "arr[19] = "${tmp}
 27 echo "arr[20] = "${arr[20]}
 28 echo "All elements: "${arr[*]}
 29
 30 echo "len(arr) = "${#arr[*]}
 31 echo "len(arr[1]) = "${#arr[1]}
 32 echo "len(arr[20]) = "${#arr[20]}

Outcome:

# bash ./array.sh
  Initialized arr: 1 1 2 3 5 8 13
  Mess a bit with arr...
  set: arr[0]=13
  set: arr[20]=20
  arr[19] =
  arr[20] = 20
  All elements: 13 1 2 3 5 8 13 20
  len(arr) = 8
  len(arr[1]) = 1
  len(arr[20]) = 2

Together with Loop

A=1
my_arry=($A B C D)
echo "第一个元素为: ${my_arry[0]}"
echo "第二个元素为: ${my_arry[1]}"
echo "第三个元素为: ${my_arry[2]}"
echo "第四个元素为: ${my_arry[3]}"

echo "-------FOR循环遍历输出数组--------"
for i in ${my_arry[@]};
do
  echo $i
done

echo "-------::::WHILE循环输出 使用 let i++ 自增:::::---------"
j=0
while [ $j -lt ${#my_arry[@]} ]
do
  echo ${my_arry[$j]}
  let j++
done

echo "--------:::WHILE循环输出 使用 let  "n++ "自增: 多了双引号,其实不用也可以:::---------"
n=0
while [ $n -lt ${#my_arry[@]} ]
do
  echo ${my_arry[$n]}
  let "n++"
done

echo "---------::::WHILE循环输出 使用 let m+=1 自增,这种写法其他编程中也常用::::----------"
m=0
while [ $m -lt ${#my_arry[@]} ]
do
  echo ${my_arry[$m]}
  let m+=1
done

echo "-------::WHILE循环输出 使用 a=$[$a+1] 自增,个人觉得这种写法比较麻烦::::----------"
a=0
while [ $a -lt ${#my_arry[@]} ]
do
 echo ${my_arry[$a]}
 a=$[$a+1]
done

Outcome:

# bash array_loop.sh
  第一个元素为: 1
  第二个元素为: B
  第三个元素为: C
  第四个元素为: D
  -------FOR循环遍历输出数组--------
  1
  B
  C
  D
  abc
  -------::::WHILE循环输出 使用 let i++ 自增:::::---------
  1
  B
  C
  D
  abc
  --------:::WHILE循环输出 使用 let  n++ 自增: 多了双引号,其实不用也可以:::---------
  1
  B
  C
  D
  abc
  ---------::::WHILE循环输出 使用 let m+=1 自增,这种写法其他编程中也常用::::----------
  1
  B
  C
  D
  abc
  -------::WHILE循环输出 使用 a=1 自增,个人觉得这种写法比较麻烦::::----------
  1
  B
  C
  D
  abc

Arguments

  1 #!/bin/bash
  2
  3 echo "Shell 传递参数实例!";
  4 echo "执行的文件名:$0";
  5 echo "第一个参数为:$1";
  6 echo "第二个参数为:$2";
  7 echo "第三个参数为:$3";
  8
  9 if [ -n "$1" ]; then
 10   echo "包含第一个参数"
 11 else
 12   echo "没有包含第一参数"
 13 fi
 14
 15 echo "参数个数为:$#";
 16 echo "传递的参数作为一个字符串显示:$*";
 17
 18 echo "-- \$* 演示 ---"
 19 for i in "$*"; do
 20   echo $i
 21 done
 22
 23 echo "-- \$@ 演示 ---"
 24 for i in "$@"; do
 25   echo $i
 26 done
 27
 28 echo "-- \$\$ 演示 ---"
 29 echo "脚本运行的当前进程 ID 号"
 30 echo $$
 31
 32 echo "-- \$! 演示 ---"
 33 echo "后台运行的最后一个进程的 ID 号"
 34 echo $!
 35
 36 echo "-- \$- 演示 --"
 37 echo "显示Shell使用的当前选项,与set命令功能相同"
 38 echo $-
 39
 40 echo "-- \$? 演示 --"
 41 echo "显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误"
 42 echo $?

Outcome:

# bash ./arg.sh 1 2
  Shell 传递参数实例!
  执行的文件名:./arg.sh
  第一个参数为:1
  第二个参数为:2
  第三个参数为:
  包含第一个参数
  参数个数为:2
  传递的参数作为一个字符串显示:1 2
  -- $* 演示 ---
  1 2
  -- $@ 演示 ---
  1
  2
  -- $$ 演示 ---
  脚本运行的当前进程 ID 号
  11959
  -- $! 演示 ---
  后台运行的最后一个进程的 ID 号

  -- $- 演示 --
  显示Shell使用的当前选项,与set命令功能相同
  hB
  -- $? 演示 --
  显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误
  0

Operator

Arithmetic Operator

#!/bin/bash

a=10
b=20

val=`expr $a + $b`
echo "a + b : $val"

val=`expr $a - $b`
echo "a - b : $val"

val=`expr $a \* $b`
echo "a * b : $val"

val=`expr $b / $a`
echo "b / a : $val"

val=`expr $b % $a`
echo "b % a : $val"

if [ $a == $b ]
then
   echo "a 等于 b"
fi
if [ $a != $b ]
then
   echo "a 不等于 b"
fi

Relational Operator

#!/bin/bash

a=10
b=20

if [ $a -eq $b ]
then
   echo "$a -eq $b : a 等于 b"
else
   echo "$a -eq $b: a 不等于 b"
fi
if [ $a -ne $b ]
then
   echo "$a -ne $b: a 不等于 b"
else
   echo "$a -ne $b : a 等于 b"
fi
if [ $a -gt $b ]
then
   echo "$a -gt $b: a 大于 b"
else
   echo "$a -gt $b: a 不大于 b"
fi
if [ $a -lt $b ]
then
   echo "$a -lt $b: a 小于 b"
else
   echo "$a -lt $b: a 不小于 b"
fi
if [ $a -ge $b ]
then
   echo "$a -ge $b: a 大于或等于 b"
else
   echo "$a -ge $b: a 小于 b"
fi
if [ $a -le $b ]
then
   echo "$a -le $b: a 小于或等于 b"
else
   echo "$a -le $b: a 大于 b"
fi

Outcome:

10 -eq 20: a 不等于 b
10 -ne 20: a 不等于 b
10 -gt 20: a 不大于 b
10 -lt 20: a 小于 b
10 -ge 20: a 小于 b
10 -le 20: a 小于或等于 b

Boolean Operator

#!/bin/bash

a=10
b=20

if [ $a != $b ]
then
   echo "$a != $b : a 不等于 b"
else
   echo "$a != $b: a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
   echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
   echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
   echo "$a 小于 100 或 $b 大于 100 : 返回 true"
else
   echo "$a 小于 100 或 $b 大于 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
   echo "$a 小于 5 或 $b 大于 100 : 返回 true"
else
   echo "$a 小于 5 或 $b 大于 100 : 返回 false"
fi

Outcome:

10 != 20 : a 不等于 b
10 小于 100 且 20 大于 15 : 返回 true
10 小于 100 或 20 大于 100 : 返回 true
10 小于 5 或 20 大于 100 : 返回 false

Logical Operator

#!/bin/bash

a=10
b=20

if [[ $a -lt 100 && $b -gt 100 ]]
then
   echo "返回 true"
else
   echo "返回 false"
fi

if [[ $a -lt 100 || $b -gt 100 ]]
then
   echo "返回 true"
else
   echo "返回 false"
fi

Outcome:

返回 false
返回 true

String Operator

#!/bin/bash

a="abc"
b="efg"

if [ $a = $b ]
then
   echo "$a = $b : a 等于 b"
else
   echo "$a = $b: a 不等于 b"
fi
if [ $a != $b ]
then
   echo "$a != $b : a 不等于 b"
else
   echo "$a != $b: a 等于 b"
fi
if [ -z $a ]
then
   echo "-z $a : 字符串长度为 0"
else
   echo "-z $a : 字符串长度不为 0"
fi
if [ -n $a ]
then
   echo "-n $a : 字符串长度不为 0"
else
   echo "-n $a : 字符串长度为 0"
fi
if [ $a ]
then
   echo "$a : 字符串不为空"
else
   echo "$a : 字符串为空"
fi

Outcome:

abc = efg : a 不等于 b
abc != efg : a 不等于 b
-z abc : 字符串长度不为 0
-n efg : 字符串长度不为 0
abc : 字符串不为空

File Test Operator

#!/bin/bash

file=${PWD}"/test.sh"

echo "file=${file}"

if [ -r $file ]
then
   echo "文件可读"
else
   echo "文件不可读"
fi
if [ -w $file ]
then
   echo "文件可写"
else
   echo "文件不可写"
fi
if [ -x $file ]
then
   echo "文件可执行"
else
   echo "文件不可执行"
fi
if [ -f $file ]
then
   echo "文件为普通文件"
else
   echo "文件为特殊文件"
fi
if [ -d $file ]
then
   echo "文件是个目录"
else
   echo "文件不是个目录"
fi
if [ -s $file ]
then
   echo "文件不为空"
else
   echo "文件为空"
fi
if [ -e $file ]
then
   echo "文件存在"
else
   echo "文件不存在"
fi

Outcome:

file=/home/yzy/Projects/shell/test.sh
文件可读
文件可写
文件可执行
文件为普通文件
文件非目录
文件不为空
文件存在

Function

  1 #!/bin/bash
  2
  3 echo "======================================================="
  4 demoFun(){
  5   echo "这是我的第一个 shell 函数!"
  6 }
  7 echo "-----函数开始执行-----"
  8 demoFun
  9 echo "-----函数执行完毕-----"
 10 echo "======================================================="
 11 funWithReturn(){
 12   echo "这个函数会对输入的两个数字进行相加运算..."
 13   echo "输入第一个数字: "
 14   read aNum
 15   echo "输入第二个数字: "
 16   read anotherNum
 17   echo "两个数字分别为 $aNum$anotherNum !"
 18   return $(($aNum+$anotherNum))
 19 }
 20 funWithReturn
 21 echo "输入的两个数字之和为 $? !"

Outcome:

=======================================================
-----函数开始执行-----
这是我的第一个 shell 函数!
-----函数执行完毕-----
=======================================================
这个函数会对输入的两个数字进行相加运算...
输入第一个数字:
1
输入第二个数字:
2
两个数字分别为 1 和 2 !
输入的两个数字之和为 3 !

Useful Function:

function mcd() { [ -n "$1" ] && mkdir -p "$@" && cd "$1"; }

Reference