logo

Bash - Overview

Last Updated: 2023-02-05

Bash is (almost) universally available on Linux, macOS, and even Windows.

The official manual: http://www.gnu.org/software/bash/manual/bash.html

Check Bash Version

  • bash --version
  • echo "${BASH_VERSION}"
  • Ctrl+x Ctrl+v

Bash Script

bash syntax: https://devmanual.gentoo.org/tools-reference/bash/index.html

Evaluate numbers

$((i-1))

Check if exists

if [ -d foo ]; then
    mkdir foo
fi

Loop

for S in FOO BAR BAZ
do
    ...
done

Skeleton of a bash script

#!/bin/bash

usage="Usage: server.sh (start|stop)"

# command is 'start' or 'stop'
command=$1

case $command in

    (start)
        ...
        ;;

    (stop)
        ...
        ;;

    (*)
        echo $usage
        exit 1
        ;;
esac

Redirect StdErr to StdOut

Use 2>&1

$ (do whatever) > /home/ubuntu/`date +"%Y%m%d"`.log 2>&1

2>&1 indicates that the standard error (2>) is redirected to the same file descriptor that is pointed by standard output (&1).

Image Not Found

Error

dyld: Library not loaded: /usr/local/opt/readline/lib/libreadline.6.dylib
  Referenced from: /usr/local/bin/bash
  Reason: image not found
Trace/BPT trap: 5

Solution

Reinstall bash

$ brew upgrade bash

Count lines in markdown files

for file in `find ../src -name '*.md'`; do
  wc -l ${file}
done | sort -n > ../_tmp/result.txt

Change -l to -w to count words.

yes or no

Some commands/programs will pause to ask you y or N. To Answer that automatically, use yes or yes n for no

$ yes | xxxx
$ yes n | xxxx

Style Guide

Use "$foo", or "${foo}", not $foo

Global Search And Replacement

$ find / -name game
$ find . -type f -name '*.txt' -exec sed -i '' s/this/that/g {} +

List the largest files/directories

If you want to find and print the top 10 largest files names (not directories) in a particular directory and its sub directories

$ find . -printf '%s %p\n'|sort -nr|head

To restrict the search to the present directory use -maxdepth 1 with find.

$ find . -maxdepth 1 -printf '%s %p\n'|sort -nr|head

print the top 10 largest "files and directories":

$ du -a . | sort -nr | head

Environment Variables

  • PATH: where to look for commands
  • SHELL: default is /bin/bash
  • HOME: default is /home/<your_username>/
  • USER: your username

Alias

$ alias sayhello='echo hello'
$ sayhello
hello

Wildcards

  • *: matches any characters
  • ?: matches one and only one character
  • [abc]: matches a or b or c
  • [!abc]: matches any characters other than a or b or c
  • {abc, def}: matches abc or def
  • {1..5}: generates the sequence 1 2 3 4 5

Input/Output

A shell opens 3 standard IO streams:

  • 0: standard input stdin
  • 1: standard output stdout
  • 2: standard error stderr

They are basically file handles ("Everything is a file").

Redirect

  • < redirects stdin, e.g. $ sort < /etc/group

  • > redirects stdout, e.g. $ echo 'hello' > hello.txt

  • 2> redirects stderr, e.g. 2> will redirect stderr to errors.txt:

    $ find / -name term 2> errors.txt
    
  • 2>&1 assigns stream 2 to 1, so all stderr is also showing instdout, e.g.

    $ find / -name term 2>&1 > all.txt
    
  • | (a pipe) transfers the stdout as the input of next segment

Start Daemon

if kill -0 $pid > /dev/null 2>&1; then
    echo Database is already running ...
else
    echo Starting Database ...
    bin/mongod &
fi

Step by Step:

  • kill -0 $pid: -0 for testing if the pid is available to kill. It will return 0 if you can kill <pid>, 1 if <pid> is invalid or you do not have access.
  • ... > /dev/null 2>&1: redirect the output to /dev/null, a blackhole. 2 stands for STDERR, 1 for STDOUT. This command means redirect STDOUT to /dev/null, and redirect STDERR to STDOUT(which is /dev/null), so both STDOUT and STDERR will be quiet. Remember the & before destination.
  • bin/mongod &: if it is not running, start the daemon. Remember the & for running in the background.

Wait before it is up:

while true; do
    sleep 1
    if pgrep mongod; then
        break
    fi
done

Stop Daemon

Similar to the previous section.

if kill -0 $pid_mongod > /dev/null 2>&1; then
    echo Stopping mongod Server ...
    kill -9 $pid_mongod
else
    echo No mongod Server to stop ...
fi

Different from the POSIX shell

  • [[ condition ]] does not work; use [ condition ]
  • Arrays do not work; use IFS
  • Local variables do not work; use a subshell