• Home
  • Store
  • Blog
  • Contact
  • Home
  • Store
  • Blog
  • Contact
  • #linux
  • |
  • #commandline
  • |
  • #softwareengineering
  • |
  • #embeddedsystems
  • |
  • #compilers
  • ...
  • View All >>

A Quick Intro to Linux Shell Scripting for Windows Developers

2016-11-18 - By Robert Elder

     This article is intended to provide an extremely brief and basic introduction to the Linux shell scripting.  Special emphasis will be placed on using shell scripts for the purpose of automated testing.  The intended audience is people who don't have much experience Linux command line before, but may be familiar with software development on Windows platforms.  An interested reader may also benefit from reading A Quick Intro to Linux Command Line for Windows Users.

What is A Shell Script?

     A 'shell script' is a computer program that contains commands that one could (with few exceptions) just as easily type into a command shell one-by one.

     A command shell is a command-line interface that allows you to tell the operating system kernel to do various useful things like launch a process, write to disk, or talk to a peripheral.  There are many common shells in Linux/Unix and each has their own flavour of syntax:

  • bash
  • dash
  • sh
  • zsh
  • tsch

     This discussion will focus specifically on writing scripts for the bash shell.  Since what we'll be doing is very simple, the syntax is likely to be mostly identical in all other major shells that are used on Linux.  If you'd like more background on Linux commands you can check out an overview of basic Linux commands here.

Writing Your First Shell Script

     For starters, here are 4 basic Linux commands:

uname
date
whoami
free

     You can type these into a terminal one by one, or you can put them all into a file, one on each line as they are above and execute them all at once.

Making Your Script Executable

      Let's say you put your commands in a file called 'myscript'.  Before you run the script, check its permissions by running this command

ls -latr

in the directory where myscript is, you might see something like this:

total 24
drwxrwxrwt 12 root   root   20480 Nov 18 19:25 ..
-rw-rw-r--  1 robert robert     0 Nov 18 19:26 myscript
drwxrwxr-x  2 robert robert  4096 Nov 18 19:26 .

     Below is a highlighted view that identifies 3 different permission groupings for the myscript file:

-rw-rw-r--  1 robert robert     0 Nov 18 19:26 myscript

     In Linux, file permissions are separated into three groups as you can see above:  In this example they have been highlighted as user permissions green, group permissions red, and other permissions blue.  Each of user, group and other has a flag for Readable (r), Writable (w), and Executable (x).  If one of these permissions is turned off you will see '-' instead of r, w or x.

     If you're paying attention, you'll note that none of the user, group or other has the executable permission set on the myscript file.  We can give the user the Executable permission by running this command:

chmod u+x myscript

     And if we check the file permissions again, you'll see that the execute permission is now set for the user:

-rwxrw-r--  1 robert robert     0 Nov 18 19:26 myscript

     In the 'chmod' command that we issued above the 'u' stands for 'user' and the '+' stands for 'add these permissions', finally the 'x' stands for 'Executable'.  For me, the current user is 'robert', and that's also the user you see displayed in the example above.  For you, this name will be different.

     Now, we are finally able to run out script!  You can run myscript by running the following command:

./myscript

     When I run this, I get the following output:

Linux
Fri Nov 18 20:27:15 EST 2016
robert
              total        used        free      shared  buff/cache   available
Mem:       16334608     1870044    12434248      106212     2030316    13981212
Swap:      19530748           0    19530748

     If you get this instead:

bash: ./myscript: Permission denied

you have most likely not set the permissions correctly to execute the script.

Add A Shebang To Your Script

     Next, you should add a Shebang to your script:

#!/bin/bash

so you end up with

#!/bin/bash
uname
date
whoami
free

     The shebang will identify which shell should be used to run your script.  You should always include a shebang at the start of your scripts, but often the script will still be able to run without one and will simply use the default shell.

How To Capture Program Return Codes

     When you run a program (or a script, or a command) a return code will be available to indicate success or failure.  By convention, a return code of '0' means success, and any non-zero return code generally means an error.  In bash you can get the return code of the last command using:

$?

     You will even get a return code from running any shell command:

date
echo "The return code is "$?

Variables

     In bash you can create a variable and give it a value by doing the following:

my_variable=1234

     Note that variable assignments are WHITESPACE SENSITIVE:

#  This will work
my_variable=12
#  This NOT will work
my_variable =34
#  This NOT will work
my_variable = 56

     Also note that when you do a variable assignment, you leave off the '$' sign, but when you reference the variable you need to use it:

my_variable=1234
echo "Here is the value of my_variable: "$my_variable

     There are cases where you may want to surround the variable name with '{', '}' characters in order to avoid ambiguity.

my_variable=1234
echo "Here is the value of my_variable: "__${my_variable}__

     You can also place the variable inside of double quotes and it will still be interpolated:

my_variable=1234
echo "Here is the value of my_variable: ${my_variable}"

Using If Statements

     Let's combine what we've just learned and do something useful with an if statement:

#!/bin/bash

#  Try to make a folder called 'foo'
mkdir foo
#  Grab the return code to see if it worked
RETURN_CODE=$?

if [ ${RETURN_CODE} -eq 0 ]; then
	echo "The return code was 0."
else
	echo "The return code was non-zero."
fi

     The above script will try to create the directory 'foo', and then detect whether the command ran successfully or not.  If we run this script 2 times in a row, the 'mkdir' command will fail the second time because the directory 'foo' will already exist:

./myscript
The return code was 0.

./myscript
mkdir: cannot create directory ‘foo’: File exists
The return code was non-zero.

Pipes and Output Re-direction

     By default most of the output of a command or program goes to what's called 'stdout' which just gets displayed on the terminal you're currently using.  You can take output on 'stdout' and put it in a file by using the '>' character:

ls > files_list

     In the above examples, the file 'files_list' will now contain the output of the 'ls' command.

     There is also something called 'stderr' which is often used to display error messages.  You can redirect stderr to file by using '2>' instead:

ls non_existing_file 2> error_message

     Now the file 'error_message' will contain the resulting error message from trying to list details on a file that does not exist.  If the file did exist, there would be nothing in the 'error_message' file.

     Another way you can redirect input/output it to put the output of one command directly into the input of another command:

ls | sort

     The above will list all files in the current directory, and then send them into another program called 'sort' that will sort them.

     

Evaluate A Subshell

     One very useful thing you can do in bash is evaluate a bash command (or program or script) and assign the output of that to a variable:

THE_DATE=$(date)
echo "${THE_DATE}"

     The '...' below can be pretty much any shell command that you could directly into the shell:

$(...)

     For example you can even use an entire shell pipe which can be assigned to a variable:

THE_RESULT=$(head /dev/urandom | xxd | grep 1 | sort -n)

Sending Parameters to A Script

     If you want to run a script from your shell and pass in parameters, like this:

./myscript 1 hello "hi there"

     The above example sent 3 parameters.  Parameters are separated by whitespace, expect for whitespace in between quotes.  You can access the parameters in your script by typing ${<parameter number>}.  For example, if my script contained the following and was run with the previous command:

echo "First Parameter: ${1}"
echo "Second Parameter: ${2}"
echo "Third Parameter: ${3}"
echo "Total number of parameters is: ${#}"

     The output would be

First Parameter: 1
Second Parameter: hello
Third Parameter: hi there
Total number of parameters is: 3

Environment Variables

     In every shell there are a number of environment variables that keep relevant information such as the default locations to look for executables, sessions ids and a number of other things.  To find out what your current environment variables are, you can use this command:

env

     The output of this command is rather verbose, so I won't paste it all here, but if I run

env |  grep "^PATH"

     I get the following:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

Conclusion

     In this article we've seen some basic ideas that can get you started in writing shell scripts on Unix.  To re-cap these features are: shebangs, file permissions, return codes, variables, if statements, pipes and I/O redirection, sub-shell evaluation, sending parameters, and environment variables.  This should be enough to get you started with automated testing by allowing you to automatically run programs and check return codes.  There are a lot more details to each of the features we've seen so far but in the interest of keep this article short I've left most of them out.

A Surprisingly Common Mistake Involving Wildcards & The Find Command
Published 2020-01-21
$1.00 CAD
Terminal Block Mining Simulation Game
A Guide to Recording 660FPS Video On A $6 Raspberry Pi Camera
Published 2019-08-01
The Most Confusing Grep Mistakes I've Ever Made
Published 2020-11-02
Use The 'tail' Command To Monitor Everything
Published 2021-04-08
An Overview of How to Do Everything with Raspberry Pi Cameras
Published 2019-05-28
An Introduction To Data Science On The Linux Command Line
Published 2019-10-16
Using A Piece Of Paper As A Display Terminal - ed Vs. vim
Published 2020-10-05
Join My Mailing List

Privacy Policy
Why Bother Subscribing?
  • Free Software/Engineering Content. I publish all of my educational content publicly for free so everybody can make use of it.  Why bother signing up for a paid 'course', when you can just sign up for this email list?
  • Read about cool new products that I'm building. How do I make money? Glad you asked!  You'll get some emails with examples of things that I sell.  You might even get some business ideas of your own :)
  • People actually like this email list. I know that sounds crazy, because who actually subscribes to email lists these days, right?  Well, some do, and if you end up not liking it, I give you permission to unsubscribe and mark it as spam.
© 2025 Robert Elder Software Inc.
Privacy Policy      Store Policies      Terms of Use