Linux Shell Basics


Introduction to Linux and the Command Line

The Classes server (classes.csc.lsu.edu) is a Linux server. Linux (more properly GNU/Linux) is a combination of the Linux operating system kernel and GNU utilities. When you login via an SSH client (such as Putty), the system starts up a text-based "shell" which allows you to navigate your portion of the file system and run commands.


Basic Shell Commands

This is best done as an interactive tutorial. Sign in to the Classes server (click here if you don't know how to do that) and run each of the following commands in turn and observe the output as you go along. Don't type the dollar sign! The command is everything after the first dollar sign (including any other dollar signs later in the line).

If you have already created some files on the server and have some basic knowledge of shell commands, you may want to skip ahead to the command summary. If not, be careful not to overwrite or remove your existing files.

$ pwd

This prints your working directory. You can also see an abbreviated form of your working directory in your prompt just before the dollar sign. My prompt with the output of pwd looks like this:

cs270099@classes:~$ pwd
/classes/cs2700/cs270099

From the prompt, we can see that I'm logged in as user cs270099. The server name is "classes" and my current working directory is ~ which is a symbol representing my home directory (the directory you always start in when you sign in to the server).

Now run the four separate commands below, one at a time.

$ mkdir tdir0
$ touch file1
$ touch file2
$ ls

The mkdir command creates a directory (aka folder) named "tdir0" in your current working directory (still your home) while touch creates empty files with the name you specify. Touch has other uses, but we use it here to quickly create empty files so we can practice moving and copying them. Finally, ls shows the contents of your current directory which now contains our test directory and two files. Let's move a file into tdir0.

$ mv file2 tdir0/
$ ls

By running ls immediately after mv, you can see that file2 is no longer in your home directory. Let's change our working directory to tdir0 and run ls again.

$ cd tdir0
$ ls

You should see that file2 made it into the tdir0 directory. The mv command is also used to rename files (or folders) by using a filename that doesn't already exist in the second argument.

$ mv -i file2 hello.c
$ ls

You should now see hello.c instead of file2 when you list the files.

Be careful! If you specify the name of a file already in use without option -i, mv will simply erase the old file without a warning. There is no recycle or undo. Using option -i (for interactive) gives a warning prompt if the file exists. Type y or Y then enter to overwrite; anything else skips the file.

However, notice that our directory tdir0 wasn't erased with the first move command. If you use mv file folder/ the file is moved into the folder instead of overwriting the folder. If you try mv folder file mv gives you an error message.


Detailed File Listing

Let's use ls to list the contents of our home directory. Since we're not in the home directory, we can specify it with ~ the tilde symbol.

$ ls ~

We can list directories anywhere on the system regardless of our current working directory by specifying the full path (or a shortcut such as ~). We can also make directories, touch files and move files from and too any place, not just our current working directory.

$ mkdir ~/tdir1
$ mv -i ~/tdir0/hello.c ~/tdir1/hello.c
$ mv -i ~/file1 ~/tdir1/world.c
$ ls ~
$ ls ~/tdir0
$ ls ~/tdir1

You should now see the folders tdir0 and tdir1 in your home directory and hello.c and world.c in your tdir1 directory. When you listed tdir0 no results were shown because it's empty of regular files. However, the basic file listing hides some things from you. In many directories there are hidden files with names that begin with a period. You can easily create or rename such files. Anything beginning with a period will not appear in the directory listing unless you add option -a to the ls command.

$ ls -a

Your current directory (tdir0) should have only two files in it: "." and ".." which appear in every directory. These are special directories that refer to the current directory itself and the parent directory respectively. Let's change back to the home directory by using .. instead of ~ and then use ls with an additional option -l (l as in Linux).

$ cd ..
$ ls -lah

With options -lah ls provides a much more detailed directory listing. We can still see our two folders tdir0 and tdir1 and a few hidden files along with current and parent directory symbols, but there's a lot more information as well. The output of my directory listing is as follows:

total 44K
drwx------   4 cs270099 cs2700 4.0K Jan 17 19:11 .
drwxr-xr-x 147 root     root   4.0K Jan  9 21:56 ..
-rw-------   1 cs270099 cs2700 1.8K Jan 17 13:14 .bash_history
-rw-------   1 cs270099 cs2700   32 Jan 17 13:14 .lesshst
-rw-r--r--   1 cs270099 cs2700   27 Jan  9 21:56 .profile
drwxr-xr-x   2 cs270099 cs2700 4.0K Jan 17 19:12 tdir0
drwxr-xr-x   2 cs270099 cs2700 4.0K Jan 17 19:12 tdir1
-rw-------   1 cs270099 cs2700 9.7K Jan 17 13:13 .viminfo
-rw-r--r--   1 cs270099 cs2700   37 Jan 15 15:06 .vimrc

Let's look at this piece by piece. The first line shows the total size of all files in the directory combined, but it doesn't include the stuff inside folders tdir0 and tdir1 so it's not especially useful (there are other commands that can give sizes including what's in sub directories).

Immediately below the total size there are several columns. The first column shows information about file permissions. We'll skip this for now. The second column shows the number of folders inside of any folder. The . and .. are included so tdir0 and tdir1 each have 2. The current directory has 4 which we can see in the listing (. .. tdir0 and tdir1). Files have a 1 here by convention. The 3rd and 4th columns show the owner and group for each file. You should own all of your files except you don't own the parent directory which is owned by "root" on this system. The 5th column shows file sizes, but directory contents aren't included, so directories are always 4.0K (for technical reasons). The option -h causes this column to be summarized to the nearest kilobyte, megabyte, gigabyte and so on. Finally we have the date of the last time the file was accessed and the file's name.


Copying and Removing Files

Let's copy some files. Copy also allows option -i for safety:

$ cp -i tdir1/hello.c tdir2/hello.c
$ cp -i tdir1/world.c tdir2/world.c

These give you errors because directory tdir2 doesn't exist. Additionally, it would take a long time to copy multiple files individually. Let's create the directory and copy all of our .c files at once with the asterisk * wildcard. Warning! Before you start using wildcards on your own, I recommend reading the final section at the bottom of this page on Wildcards and Globs.

$ mkdir tdir2 
$ cp -i tdir1/*.c tdir2/

We'll take a closer look at how wild cards work later, but for the moment you can use an asterisk to represent anything (or nothing). In this case, it matches any file ending with .c. The target is a directory so like the mv command, it creates copies with the original name.

If the screen is getting a little messy, use clear to erase it. We can use wild cards with other commands such as ls. Let's list all of our test directories.

$ clear
$ ls -lah tdir*

You should see your .c files in both tdir1 and tdir2 if the copy went as planned.

Finally, let's delete all of the things we've created. We can delete in a few different ways. First we'll delete some things in a slow but safe manner.

$ rmdir tdir0
$ rmdir tdir1

The rmdir command removes directories, but only empty directories. The second invocation of rmdir gives an error because tdir1 contains files. Let's use rm to remove the files and then the directory. Option -i prompts before each removal which is often a good idea when using a wildcard.

$ rm -i tdir1/*.c
$ rm -i tdir1

The files are removed, but rm won't remove a directory (even if it's empty). Warning! Don't type the next command if you have anything in your tdir directories that you want to keep. This command will delete any directory (and contents) beginning with tdir.

$ rm -r tdir*

The option -r stands for recursive and will allow rm to delete directories and their contents. Using a wild card without -i we can quickly delete all of our remaining test directories and their contents. You should realize the potential for huge accidents when using rm this way. However, if you were deleting a lot of files, interactive mode is impractical. As with cp and mv, you cannot undo the delete and there is no recycle bin.

Finally, if you want more information about a command, use man which is short for manual pages. You run man with the name of any command as an argument to look at the full documentation for a command. After you run the following command, use arrows to navigate the manual and press q to quit.

$ man ls

If you view man pages for other commands, you will see that these commands are very complex and powerful.


Basic Command Summary

You should review and practice the commands on your own now. In shell scripting (a kind of programming) the # symbol is used for comments similar to // in Java, C++ and (some versions of) C. I will summarize commands below and in some cases put comments above or beside them using the # symbol.


#print working directory
pwd

#make directory
mkdir dir-name

#make a new file; but won't erase an existing file
touch file-name

#list the current directory or specified directory
ls
ls -lah
ls dir-name
ls -lah dir-name

#listing with wildcards (try it)
ls -lah tdir*  #This expands any matching directory
ls -lahd tdir* #The -d option stops such expansion

#change your current directory
cd ~       #change to ~ (your home directory)
cd ~/tdir1 #change to ~/tdir1
cd ../     #change to the parent directory
cd tdir1   #change to tdir1 in your current directory


#cp and mv overwrite and destroy destination files if they exist!
#use -i for interactive mode to get a warning prompt before overwriting

#copy one file into another folder:
cp file1 folder/      #copy of file1 keeps the name file1
cp file1 folder/file2 #copy is renamed to file2

#copy file to new file in same folder
cp file1 file2

#copy many files to a folder
cp file1 file2 file3 folder/

#move or rename files (or both at once)
mv file-a file-b    #rename file-a to file-b
mv file dir1/file.c #move file into dir1 and rename to file.c
mv *.txt dir1/      #move any .txt files into dir1
mv *.txt dir1       #note: the trailing / on a directory is optional

#clear the shell screen
clear

#remove (delete) an empty directory
rmdir

#remove (delete) a file
rm file

#remove a folder and all of its contents interactively
rm -ri folder

#open man pages for a command or program
man command-name

#close the shell (logging you out of the server)
exit


Wildcards and Globs

Wildcards can be very dangerous when used improperly. Let's learn another command to make them a little safer and also learn a little more about how they work. The echo command takes a string as argument and writes it back to the screen.

$ echo Hello World!

The echo command can be used to expand some symbols. For example, if you echo ~ which represents your home directory, echo will write the full path of your directory. Try it:

$ echo ~

Echo can be very useful to see how wildcards will expand before you use them. Use touch to quickly create several files, then use echo with a wild card and see what happens.

$ mkdir testdir
$ cd testdir
$ touch file1 file2 filea fileb
$ echo file*

The shell expands the wildcard into a "glob" of file names which then end up being the argument string for echo. Echo safely prints them to the screen without taking any other action. To use a glob (created by wild card expansion) a command has to be designed to accept a list of multiple files. As an example that doesn't work (make sure you're still in testdir/ before running these):

$ touch new-file
$ cp newfile file*

You might expect the copy command to use new-file as a source and then overwrite every file in the glob with a copy of newfile. However, you get an error instead. What copy sees is:

$ cp newfile file1 file2 filea fileb

If you check the man pages for cp, you'll see the following synopsis

SYNOPSIS
       cp [OPTION]... [-T] SOURCE DEST
       cp [OPTION]... SOURCE... DIRECTORY
       cp [OPTION]... -t DIRECTORY SOURCE...

DESCRIPTION
       Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.

The first form (without option -T) and second form represent your typical uses of copy. You see ... after SOURCE in the second and third form but nowhere else. The Description verifies the meaning. The cp command can work with a single source and destination; or it works with one or more sources and one destination directory. The ... symbol is usually your cue to use wildcards to generate a glob of filenames.

Let's generate a few more globs to illustrate additional wildcards. The asterisk * matches 0 or more of any character. The ? matches exactly one (not 0) of any character. We can put ranges or lists of characters in angle brackets. Angle bracket notation can get very complex (and be equally useful at times).

$ touch file.c

$ touch filez

$ echo file?

$ echo file[b-z]   #match exactly any one character from b-z

$ echo file[b-z,2] #as above but including 2 as well

$ echo *file

$ echo *file*      #this will match all of our test files

You can clear the directory with 'rm *file*'. Globs are very powerful and consequently both very useful and very dangerous.