Introduction to Bash Shell Scripting

Shell is a program which runs inside Terminal. Whenever user enters any command into Terminal, then its executed by Shell Program. For example – When you enter Command ls -1 ~/Documents inside Terminal then shell program will take it as an input, interpret it and execute it, then print out output on Terminal window. There can be different types of Shell like Bourne Shell(Bash Shell), Korn Shell, C Shell.

In this article, I’ll discuss and explain about Bash Shell (Kind of an introductory Bash Tutorial). Let’s first discuss about what’s Bash? Bash is a shell or command language interpreter for GNU Operating System. The name is an acronym for the ‘Bourne-Again SHell, a pun on Stephen Bourne, the author of the direct ancestor of the current Unix shell sh, which appeared in the Seventh Edition Bell Labs Research version of Unix.

Let’s discuss different aspects of Bash Scripting one-by-one.

Wildcards in Bash Scripting

Wildcards in Bash are a shorthand way for sets of files having similar names. For example – If in some folder you’ve three files named – computer.txt, c.txt, computing.txt then all of these can be shortened to c*. So writing ls c* will print out names of all files starting with character c in the current directory.

Wildcards in Bash Shell Scripting

For example – In above picture you can clearly see that current directory have five files – computer.txt, c.txt, computing.txt, a.txt, b.txt.
But using ls c* only lists files starting with character c.

Similar to this, Wildcards can be used for comparing characters from start or end of file name. Let’s see what other Wildcards does Bash Support.

Below is a Table containing Bash Shell Scripting Wildcards and their description

WildcardDescription
*Match against zero or more consecutive characters
?Match against just a single character
[set]Match against any character in the set
[^set]
[!set]
Any Single character which is not in given set

One of my favorite use case of using wildcards is to delete unnecessary files from a directory. For example – If a directory have hundred thousand photos having filenames as photo_1.jpg, photo_2.jpg, photo_3.jpg, ………………………, photo_10000.jpg
And you want to remove all photos whose filename ends with one single zero like photo_10.jpg, photo_20.jpg and so on. Then realistically on Mac there is no way to do so. But this can be done using Bash, that too with just one command line rm *0.jpg

*0.jpg will match against all photos whose file name ends with a zero and rm will remove those. Quite Simple.

Do not that Wildcards cannot be used for matching against leading period or trailing directory slash(/)

Brace Expansion in Bash Scripting

Similar to wildcards, expressions with curly braces also expand to become multiple arguments to a command. For example – Brace Expansion Com{ P, PP, PPP, PPPP }uter will match against ComPuter, ComPPuter, ComPPPuter, ComPPPPuter file names.

Shell Variables in Bash Scripting

Similar to programming languages, in Bash Scripting also variables can be defined as AVAR = 10, these variables are created for temporarily purposes. When Shell exits these get destroyed and cannot be used again when Shell is opened again.
Below are some recommendations to keep in mind while dealing with variables in Bash.

  • Use all uppercase letters for defining variables in Bash.
    • AVAR is a good variable name
    • avar is a bad variable name
  • For accessing value of already defined variable use dollar sign before its name. Like for accessing AVAR variable value use $AVAR.

Despite these user defined variables, Bash does have some internally defined variables. Don’t use name of these internally defined variables as name of user-defined variables.

Internally Defined Variables in Bash

VariableDescription
HOMEStores home directory like /Users/gagan
LOGNAMEStores name of user, who is currently logged in
OLDPWDStores shell’s previous directory
PATHStores Shell’s Search Path
PWDStores Shell’s Current Working Directory
SHELLStores path to Shell like /bin/bash
TERMStores what type of terminal is being used
USERStores login name

How to See value of a defined Variable?

If you’ve already defined a variable and have also assigned some value to it. Then it’s value can be printed to terminal using echo $VARIABLE command.

How to See value of a defined Variable in Bash Scripting?

How to print all environment variables in Bash?

For seeing all of environment variables currently defined in a Bash Shell, just use command printenv. This will print out all of environment variables and their values as well in the Terminal Window.

How to print all environment variables in Bash?

Search Path in Bash Scripting

Whenever enter is pressed after typing a command in Terminal Window, then Shell will first look for definition(Source Code) of that command in filesystem directories like /bin or /usr/bin. Once Shell found source code for executing user entered commands then only it will execute the command.

Now definition/source code of these commands can be stored anywhere on a MAC Filesystem, not necessarily in /bin or /usr/bin directories. That’s why Bash have defined a variable called PATH which is a sequence of semi-colon separated absolute paths of directories to look into, while searching for definition/source code of a command. Usually PATH variable’s value looks like.

bash: /Library/Frameworks/Python.framework/Versions/3.9/bin:/usr/local/etc/php/8.0/bin
:/Library/Frameworks/Python.framework/Versions/3.9/bin:/Users/gagan/opt/anaconda3/bin
:/Library/Frameworks/Python.framework/Versions/3.8/bin:/usr/local/bin:/usr/bin:/bin
:/usr/sbin:/sbin:~/.npm-global/bin/:/Applications/VMware: No such file or directory

So whenever a command let’s say ls is entered then Bash will look for it in all of paths listed in PATH variable and once found then execute it.

Aliases in Bash Scripting

Bash built-in command alias can be used for defining a shorthand command for a longer command. For example – If in your Bash Script, you need to use ls -1 (This command lists all files/directories in Current Working Directory). Then you can just store this command as l1 using alias l1 = ‘ls – 1’. Also if for some reason, you need to destroy this new alias variable just use command unalias l1.
Using variable aliases can be helpful for you need to use some Bash Command again and again.

Input/Output Redirection in Bash Scripting

If in case, you want to read some file as an input to a Bash Command or want to write output of a command to some file. Then use < for reading file in, > for writing to a file.

  • some command < infile means command is reading in content of infile
  • some command > outputfile means whatever content will be returned by some command would be written into outputfile

Pipes in Bash Scripting

Pipes in Bash Scripting allows to make connection between different commands. So if you want output of a command to become input of some other command then just use Pipe. In Bash pipe is represented as | symbol.
For example – For command ls | wc -1 output of first command(ls) will become input of second command(wc -1) and whole command ls | wc -1 will print out output returned by second command to terminal window.
Pipes are quite simple to implement but can be quite useful for doing multiple operations in a chain.

Combining Commands in Bash Scripting

Pipes can be quite useful for chaining different commands, but what if you need to make choices out of three commands. That’s why Bash support Combining of commands. So command1 ; command2; command3; whole command would execute each one of individual command one-by-one.
Below are some command combining scenarios =>

  • Stopping Executing even if any of command fails
    • command1 && command2 && command3
  • Stop Execution as soon as one command succeeds
    • command1 || command2 || command3

Strings Quoting in Bash Scripting

Similar to other programming/scripting languages, Bash also support double/single quotes for creating Strings. For example – “This is Computer Science Hub” and ‘You are using website Computer Science Hub’ are both strings in Bash. But there is a little difference between single/double quotes when string have Shell Variables in it.
(Assuming WEBSITE = ‘Computer Science Hub’)

  • When string is enclosed by single quotes then Bash will not evaluate Shell Variables.
    • So echo ‘This is $WEBSITE’ command will evaluate to This is $WEBSITE.
  • When string is enclosed by double quotes then Bash will evaluate Shell Variables.
    • So echo “This is $WEBSITE” command will evaluate to This is Computer Science Hub.

Some History Related Bash Commands

  • history – Print list of commands which have been executed in current session of Shell
  • history N – Print most recent N commands in command execution history of current session of Shell
  • history -c – Clears all of command execution history of current session of Shell
  • !! – Rerun previously executed command
  • !N – Rerun command number N from command execution history of current session of Shell
  • !-N – Rerun command typed in Shell N commands ago

Bash Jobs Commands

For doing Job Management/Memory Management Bash uses some Job Control Commands.
Below is a list of Job Commands in Bash Shell Scripting.

  • jobs – This commands lists all of jobs
  • & – Runs a specific job in background
  • ^Z – Suspends current job running in foreground
  • suspend – Suspend a Shell
  • fg – Unsuspend a suspended job and brings it to foreground
  • bg – Makes a suspended job to run in background

In above list of Job Commands, foreground means Running a job in a shell and doesn’t allow another command to be entered in Shell by user.
background means Running a job in shell such that it doesn’t block user to enter in another command in Shell.
suspend meanings temporarily stopping execution of a job running in foreground.

This is how Bash does Jobs Management.

Killing an Ongoing Command Execution in Bash Scripting

Any running Bash Command in a Shell can be killed using command ^C. But if command is running in background then you need to bring it to foreground before killing it using ^C. This is not the best way to kill a command execution and stop it. Doing this may leave shell in some weird state.
Let’s discuss about Killing a command execution safely without causing any problem.

Best Way to Kill an Ongoing Command Execution

Killing a foreground program with ^C may leave your shell in an odd or unresponsive state, perhaps not displaying the keystrokes you type. This happens because the killed program had no opportunity to clean up after itself. If this happens to you, then do following –

  1. Press ^J to get a shell prompt. This produces the same character as the Enter key (a newline) but will work even if Enter does not.
  2. Type the shell command reset (even if the letters don’t appear while you type) and press ^J again to run this command. This should bring your shell back to normal.

Final Thoughts

One of quite fascinating thing about these bash commands is that you can use these from terminal while working on some Coding Project. Moreover having basic knowledge of how does Scripting works in general is always great for having a long-term Software Engineering/Computer Science Career.
Anyway, if you have any doubt regarding anything in this article then let me know in comments below. I’ll try to reply as soon as possible for me.
Happy Bash Scripting ☺️ ☺️ ☺️

Gagan

Hi, there I'm founder of ComputerScienceHub(Started this to bring useful Computer Science information just at one place). Personally I've been doing JavaScript, Python development since 2015(Been long) - Worked upon couple of Web Development Projects, Did some Data Science stuff using Python. Nowadays primarily I work as Freelance JavaScript Developer(Web Developer) and on side-by-side managing team of Computer Science specialists at ComputerScienceHub.io

Leave a Reply

Your email address will not be published. Required fields are marked *

Recent Posts