It’s easy to get intimidated, but once you get over the initial learning curve you will see it’s not as hard as it looks. Like every other aspect of programming, you will improve with lots of practice and experience.
If you are comfortable with programming in R or Python, then the Unix/Linux command line is not so different. We will look at several useful commands, which are equivalent to functions in R. Recall that in R functions have arguments, with the general form:
RFunction(Parm1=ARG1, Parm2=ARG2, ...)
I R, a function is always followed by a set of brackets, which can be used to define arguments that are specific to that function.
The Unix/Linux commands also have arguments, but they are defined with dashes and spaces instead of () and = :
UnixFunction --Parm1 ARG1 --Parm2 ARG2
This may look confusing at first but you will get used to it. Often there are one-letter short forms for these commands, which are used with just a single dash:
UnixFunction -A ARG1 -B ARG2
That’s all you need to get started!
‘With great power comes great responsibility’ – Uncle Ben
The command line is a powerful tool. It can be used to do a lot of wonderful things, but it can also completely mess up your computer if you aren’t careful. It is very easy to accidentally delete a file with no way of recovering it. Pay close attention to the files you are working with.
Often when we log onto a new computer it’s good to explore the file system. This can be a bit disorienting at first because we have to interpret a bunch of lines of text, rather than graphics of folders and files. It can help to imagine the folders just like you do on your regular graphical user interface (e.g. MacOS, Windows, Ubuntu).
pwd
Present Working DirectoryIt’s important to check where you are in your file system. Doing this frequently will ensure that you don’t accidentally delete an important file. This will check what your directory is, equivalent to getwd()
in R:
pwd
Your output will depend on your computer and the program you are using:
MobaXTerm might loook something like this:
/home/mobaxterm
If you are using MacOS it look more like this:
/Users/UserName
where UserName
is the user name you defined when you set up the computer.
If you are using a Unix-based system like Ubuntu or CentOS, or logging onto a remote server with Compute Canada or the Queen’s University Centre for Advanced Computing (CAC), then it might look more like this:
/home/USERNAME
OR
/global/home/USERNAME
cd
Change Directory~
Getting HomeRegardless of where you are, you can use the ~
command to return to your home directory:
cd ~
pwd
Again, the output will depend on your file system. In this tutorial, we’ll represent your home directory with ~
in the output. So where you see ~
in the output, you should see one of the above directories in your own output.
mkdir
Make a DirectoryLet’s make a temporary directory:
mkdir tmp
cd
Change DirectoryLet’s move into our new directory and then see where we are at
cd tmp
pwd
~/tmp
Now we are inside the tmp
directory inside of our home directory. If we wanted to move ‘up’ one level, back to our home directory, then we type two periods:
cd ..
pwd
~
Let’s go back into the tmp
directory for now
cd tmp
ls
ListUse the ls
command to see all the files in the directory.
ls
You won’t see anything yet because there are no files in here. Let’s create a text file.
The linux/unix environment has a number of text editors available. Two really basic and easy to understand text editors are nano and pico. Unfortunately these are not installed with MobaXTerm by default; see these instructions for installing nano. OR you can type a command to get and install the nano program:
apt-get install nano
If nano is installed, we can use it to create a new text file:
nano Text.txt
NOTE: If this doesn’t work, then just open the Notepad (Windows) or textEdit (MacOS) editor, type the lines below, and then manually save it as Text.txt
inside of your ~/tmp
folder. Then quit the text editor program.
Type the following into the text file:
Line 1
Line 2
Good-bye
To save from nano, we can press Ctl-O
to Output or we can press Ctl-X
to Exit and press y to save the changes. Hit Enter to confirm that we want to use the same file name, which will replace the olde Text.txt with a new file containing our three lines of text.
Now take another look inside the folder:
ls
Text.txt
We can use the -l argument to see more detail
ls -l
total 1
-rw-r--r-- 1 UsrName UsersGrp 24 Jan 27 11:34 Text.txt
Note that this argument doesn’t need any additional parameters.
Let’s change the name of the file:
mv
Move a FileTo change the name of a file we ‘move’ the contents from the old file name to the new one:
mv Text.txt .hiddenText
Note the period in front of hiddenText. File names that start with a period are hidden by default:
ls -l
total 0
However, hidden files can be seen with the -a
parameter
ls -a -l
total 3
drwxr-xr-x 1 rob_c UsersGrp 0 Jan 27 11:37 .
drwxr-xr-x 1 rob_c UsersGrp 0 Jan 27 11:20 ..
-rw-r--r-- 1 rob_c UsersGrp 24 Jan 27 11:34 .hiddenText
Now we can see the hidden file, but also two other lines corresponding to one and two periods. We have already used the command cd ..
to change directories, so the ..
is just a symbol showing that the current ‘working’ directory is inside another ‘parent’ directory. The single dot is a symbol for the current working directory. For example, compare the output from these two lines. Why are they different?
ls -a
ls -a ./
ls -a ../
The first two lines list the files ‘linked’ to the current directory. This includes the current directory .
, the parent directory ..
, and the file .hiddenText
.
The second command lists the files in the parent directory. The specific output will depend on the operating system you are using.
cp
CopyLet’s copy our hidden file and turn it into a Bash Script. A bash script is a text file that can be used to run programs in the Unix/Linux environment.
cp .hiddenText BashScript.sh
rm
RemoveLet’s delete the old file, which we don’t need. We do this with the rm
command:
WARNING: be careful with
rm
because there is no ‘recycle bin’ in the command line. When you delete it, it’s pretty much gone!
rm .hiddenText.txt
Now open the text file with nano
or a text editor.
A bash script always begins with the line
#!/bin/bash
The order is very important here. A good way to remember the order is the phrase Shazam!, like the comic book characer. Not to be confused with kazaam, the impressively bad Shaquille O’Neal movie.
echo
OutputThe Unix/Linux equivalent of the print()
command in R is echo
. Because we are going to print the other lines as strings, we use quotation marks to clarify this for the bash interpreter. Now your file should look like this:
#!/bin/bash
# Comment -- this line will not run
# echo returns output to the user
echo "Line 1"
echo "Line 2"
echo "Good-bye"
Next we can make a more interesting program using variables, a for loop and if/then statements.
$Variable
Bash variables are set with regular text, BUT when you want to use the variable then add the $ prefix. This will make sense when we use it in the context of a for loop
for
A for statement has two components:
for
component sets up the looping variabledo
and done
statements define what to do for each iteration of the loop.Let’s add a for loop with a variable counting from 1 to 5. There are two ways we can do this:
for Count in 1 2 3 4 5
for Count in {1..5}
In the first case, you just separate each iteration by a space and you could use other things besides numbers, for example, strings defined with quotation marks, or file names.
Once the for
line is written, the next lines use do
and done
to define what to do in each iteration of the loop
for Count in 1 2 3 4 5
do
echo "This is loop number $Count"
done
Now save and exit the script.
if
We won’t include an if statement, but they are similar, with arguments defined in square brackets. Instead of do
and done
if statements use if
, then
, elif
, else
and fi
. Here’s an example:
if [ $Var1 == $Var2 ]
then
echo "Variable 1 is equal to Variable 2"
elif [ $Var1 -gt $Var2 ]
then
echo "Variable 1 is greater than Variable 2"
elif [ $Var1 -lt $Var2 ]
echo "Variable 1 is less than Variable 2"
else
echo "Variable 1 is not equal to or greater than Variable 2"
fi
In this case, specific statements are made with if
and elif
, whereas else
captures anything else that doesn’t fit in any of the if
or elif
criteria.
chmod
permissionsBefore we can run our bash script, we have to modify the file permissions. The permissions for files are shown when you run the long
version of the list command ls
:
Here’s an example
total 3
drwxr-xr-x 1 rob_c UsersGrp 0 Jan 27 11:37 .
drwxr-xr-x 1 rob_c UsersGrp 0 Jan 27 11:20 ..
-rw-r--r-- 1 rob_c UsersGrp 36 Jan 27 11:34 BashScript.sh
The first letter ‘d’ indicates whether it is a directory, and the other nine letters define the user access privileges.
The nine characters are actually 3 sets of 3 characters corresponding to (from left to right):
An example of a Group would be a lab or PI on Compute Canada, with each individual User in the group, and Others being everyone else who has access to the computer but are not in your group.
The dash -
means that permission is denied, and the three letters correspond to different kinds of use for the file:
w
- write (i.e. edit)x
- executer
- read (look but don’t change or run)To run our bash script, we need permission to execute the file, which is not set by default when we made our text file. We use the chmod command to do this.
chmod 755 BashScript.sh
Now take a look at the permissions. The three numbers correspond to permissions for each of the three levels, from 0 to 7:
Code | Permission | rwx |
---|---|---|
7 | read, write and execute | rwx |
6 | read and write | rw- |
5 | read and execute | r-x |
4 | read only | r– |
3 | write and execute | -wx |
2 | write only | -w- |
1 | execute only | –x |
0 | no access | — |
bash
Run a ScriptNow that the permissions are changed, run the file using the bash
command
bash BashScript.sh
We can add user-defined variables in our bash script in two ways.
Use the $ with numbers to indicate the order of arguments entered by the user. For example, if you add this code to your bash script:
Var1=$1
Var2=$2
Then the user would input two arguments, for example:
bash BashScript.sh 10 15
Would set Var1=10 and Var2=15
The second method is to interactively ask the user for input. Usually, you would want to prompt the user with an echo command so that they know what you are looking for. Try this:
echo "Enter a number"
read Var1
echo "Enter another number"
read Var2
echo "Your numbers are $Var1 and $Var2"
head
, tail
and less
Sometimes we are working with files that are too big to open with nano. In these cases, we may want to look at the first few lines using head
, the last few lines using tail
, or browse through the file a few lines at a time using less
Note that to exit less
you type q
man
and help
To get more information on any command, use the man command or the –help parameters:
man ls
ls --help
#
CommentsThe first thing we can do is add comments to the document. Just like in R we can add comments with #. Note the exception is the special Shazam! combination, which starts with # and appears on the first line of the bash script.