Let's play: Bash script

Let's play: Bash script

Hello all!

This article is about Bash language I have worked with a lot in my company. I would say my tasks mostly involve CLI (Command Line Interface) intensively and this is a chance to show off my often-used commands of Bash.

Let’s go!

Ref: https://itsfoss.com/bash-5-release/

What is Bash

Bash is a one of shell scripts available on UNIX OS. Some of the others are cmd and powershell which are working on Windows OS. We don’t have to install any programs before running Bash because it has been pre-installed inside.


Section: Path

In Unix, ~ indicates root path while . is current directory and .. is parent directory.

In case of current path value, we use pwd. ls is for listing files and folders in the current path. And cd is to change directories.

  • ~‌‌
    root path
  • .‌‌
    current directory
  • ..‌‌
    parent directory
  • pwd: print working directory’s name‌‌
    current path value
  • ls: list‌‌
    list of files and folder in current path
  • cd: change directory‌‌
    change directory

As the example above, ls show files and folers in the current path. Additionally, ls -la (list – long format & all) shows details that is permissions, owner name, last modified date etc. of each file/folder.

pwd displays current path value and we can change the current directory using cd with the target directory. cd ~ means change to root directory ( /root ).


Section: Files/folders management

Making a new directory with mkdir or a new empty file with touch. Want to delete a file? use rm or rm -r if that is a folder.

cp is for copying a file/folder or move/rename it with mv.

  • rm: remove‌‌
    remove a file, for a folder add -r.
  • mkdir: make directory‌‌
    making a new folder
  • mv: move
    ‌‌move or rename a file/folder
  • cp: copy‌‌
    copy a file/folder
  • touch
    ‌create an empty file

I created a new folder using mkdir test01. And access it with cd test01 then create an empty file by touch test01_a.txt. After that, copy it to a new file via cp test01_a.txt test01_b.txt.

Inside the folder "test01", I created a new folder named "test02" then move test01_b.txt using mv test01_b.txt test02/. The path of test01_b.txt has been changed to test02/test01_b.txt.

For renaming, we have to specify the name of the file after moving such as mv test01_b.txt test02/test02_b.txt.‌


Section: Permissions

We need to change permissions of the file and we can apply them by chmod while chown is for changing owners.

For some files which require advance permissions, sudo will execute it. And su is for changing users in the system.

  • chmod: change mode
    change permissions of a file/folder
  • chown: change ownership
    change owner of a file/folder
  • sudo: superuser do
    Execute some commands with advance permissions
  • su: switch user
    change user

As a figure above, ls -la of the file test01_a.txt shows its permissions as the followings:

ls -la
-rw-r--r –  1 root  root    0 Nov 10 14:27 test01_a.txt
# (-)rw-r--r – ==> text01_a.txt is a file
# -(rw-)r--r – ==> OWNER name "root" can read or write the file but cannot execute it
# -rw-(r--)r – ==> GROUP name "root" can read it but cannot write or execute it
# -rw-r--(r--) ==> OTHERS can read it but cannot write or execute it

chmod +x will add permissions to execute the file to everyone (OWNER, GROUP, OTHERS). That command will change the permissions to -rwxr-xr-x. And I use chown -R (Recursive to subfolders) to change OWNER from root to tester for itself and its subfolders.

Finally, switch user to tester with su tester.


Section: Operators

  • | (pipe)
    It is for serial execution. Left command has to be finished execution then the right one will be executed. Result will be from the right one.
  • & (ampersand)
    It is for parallel execution. The commands in each side of this operator will be executed simultaneously. Result will be from both without ordering.
  • || (logical OR)
    Respective execution. The program will be successfully executed if ANY commands are successfully executed. Result is from the very first succeeded command.
  • && (logical AND)
    Respective execution. The program will be successfully executed if ALL commands are successfully executed. Result is from all succeeded commands.

First. echo "a" | echo "b", the left command is finished then the right one is finished. Result is from the right that is “b”.

Second. echo "a" & echo "b", both are executed simultaneously and the right one is finished before the first one. Result is “b” then “a”.

Third. echo "a" || echo "b", the left command is executed successfully and the result is “a”. The right one cannot be executed. The program succeeded.

Last one. echo "a" && echo "b", the left command is executed successfully then the right one is so. The result is “a” then “b”. The program succeeded.


Section: String

We command echo to display a string or a value and cat to read a file.

There are so many commands for string decoration. I raise the sample of frequently used commands below:

  • echo
    display a string or a value
  • cat: concatenate
    read content from a file
  • sed: stream editor
    replace a string inside another string
  • grep: global search – regular expression – print
    Find and display a string inside a string with regular expression
  • cut
    do substring
echo "start"
cat sample_back.sh
echo "a dog wags its tail" | sed -e "s/dog/cat/g"
echo "a fish swims in a jar" | cut -c 1-5
echo "my telephone number is 1234" | grep -o "[0-9]*"

I have created a file named sample_back.sh containing the text “this is a sample file for reading”.

And the another file named sample_front.sh containing these commands:

  • echo "start". It will show “start”
  • cat sample_back.sh. It reads the file sample_back.sh and got the same sentence that is “this is a sample file for reading”.
  • Next, sed -e "s/dog/cat/g" is to change the word “dog” to “cat” and got the final sentence as “a cat wags its tail”.
  • cut -c 1-5 is to cut all letters (including spaces and other special characters) between position 1-5 of the original sentence. The result is “a fis”.
  • Last one, grep -o "[0-9]*" is to extract only number from “my telephone number is 1234” and got “1234”. ( [0-9]* is a regular expression for capturing numbers from 0 to 9 plus * which means any occurrence of the numbers)

Section: Conditional structures

IF-ELSE

if [[ $a == 1 ]]; then 
    echo "a is 1" 
elif [[ $a == 2 ]]; then 
    echo "a is 2" 
else 
    echo "a is not 1 nor 2"
fi 

It is just an ifthenelifthenelse and fi at the end.

FOR-loop

for i in $list; do
    echo this is $i
done

Mostly used when we have to do something to each item in a list.

WHILE-loop

while [[ $a -le 10 ]]; do # check if a less than or equals 10
    echo "$a";
    a=$((a+1)); # a = a + 1
done

Don’t make it an infinite loop.

TRY-CATCH

Literally Bash has no try-catch block but we can apply it like this.

{
    # try
} || {
    # catch
}

Code above is to run try-block, and in case of failure do run catch-block. They are linked with ||.

{
    # try
} && {
    # then
}

And the code above is to run try-block, and in case of success do run then-block. They are linked with &&.

First file – test02_v1.sh

I added exit 1 to cause an error and defined “if failed, do display this is part 2″. We got the message of part 2 as the first block run failed.

Second file – test02_v2.sh

I changed the condition to “if succeeded, do display this is part 2″. We got nothing as the first block run failed.

Third file – test02_v3.sh

I removed exit 1 and keep the condition “if succeeded, do display this is part 2″. We got both part 1 and part 2 as the first block run successfully.

These are basic error handling. They are essential for jobs to manipulate the flows.

However, please mind the spaces between brackets and the operators.


Section: Date and time

My mostly-used command is just one that is date but there are many applications.

$(date +"%Y-%m-%d")
$(date -d "-[n] day" +"%Y-%m-%d")
$(date -d "[n] day ago" +"%Y-%m-%)
$(date -d "$(date -d @[epoch_in_seconds])" +"%Y-%m-%d" )
$(date -d "$[target_date] [n] day" +"%Y-%m-%d")
if [[ $(date -d "$date_one" +%s) -le $(date -d "$date_two" +%s) ]]; then
    echo "$date_one is LESS THAN OR EQUAL TO $date_two"
else
    echo "$date_one is GREATER THAN $date_two"
fi

-d will translate a string to a date object. As the example above, -1 day is as same as 1 day ago that is yesterday so 2019-01-01 1 day means 1 day after 2019-01-01 that is 2019-01-02.

@[epoch_in_second] is UNIX epoch which is an integer form of date object such as @1546300800 equals to 2019-01-01 00:00:00 AM (more information at https://www.epochconverter.com)

+"..." defines output format. For example, +"%Y-%m-%d" means year-month-date e.g. 2019-01-10 and +"%s" means epoch format as mention before. The last format can be used to compare two dates as the last set of commands above.


Section: Externally execution

  • source
    Refer other Bash files
  • sh
    Externally execute a Bash file

First file – test01.sh contains test_var. After source test01.sh we can display the value of test_var from outside.

Second file – test02.sh contains echo command. After sh test02.sh, it triggers echo and display the text.


Section: Our own functions

Function structure is described below:

sample_func() {
  local a=$1 # local variable
  local b=$2 # local variable
  echo "first is $a and second is $b"
}

sample_func 1 2

We have to define functions before use them. And how to call them is to type their names following parameters separated by space.

As the example, we call sample_func with parameters as 1 and 2. Inside the function, value “1” will be $1 and be assigned to variable a while value “2” will be $2 then be assigned to variable b. It displays first is 1 and second is 2 at the end.


Section: Comments

There are 2 ways to add a comment

  • insert # in front of a line
  • begin a multiline comment with : <<
# this is a single-line comment
: << 'comment'
    this 
    is 
    the 
    multi-lines
    of 
    comments
comment

As the example, "b" won't be shown as it is a comment. And "d", "e", and "f" are neither as they are in multi-line comment controlled by the word a_comment.


As I said, they are most often used of mine in the jobs. There are also different commands not mentioned here. And I hope this is useful for some of you readers.

Let's see what's next.

Bye~

Credits

Show Comments