If you're interested in just the Unix tools we've used so far, there's a separate page for that.
Main article: An overview of Bash and the interactive prompt
At a glance:
Bash (which stands for Bourne again Shell) is the name of the shell program that interprets our text input and converts it into commands for the computer to run. Each time we type in a command, hit Enter, Bash evaluates/executes the command, and then prompts us for the next command.
The prompt is what Bash uses to signal that it is waiting for your next command. Prompts can be customized. For most of the examples listed on the site, the prompt will look like this:
user@host:~$
I try to preserve what the code (and its output) looks like at the prompt, which means that you cannot just copy-and-paste examples like this:
user@host:~$ for i in $items; do
echo $i
done
Main article: Text interpretation in Bash
At a glance:
For readability sake, users can separate a length command into multiple lines by appending a backslash after each line:
user@host:~$ mkdir -p January February March April \
May June July August September October November \
December
For readability sake, users can use semicolons to indicate the end of a command within a single line. This allows the user to list and execute multiple commands upon hitting Enter:
user@host:~$ mkdir -p January; mkdir -p December
The use of double-ampersands between commands will also allow the execution of multiple commands in a single line. However, unlike semicolons, if the first command fails, the second command will not run:
user@host:~$ cd some_directory_that_may_exist && rm -f *
The use of quotes allows the user to enclose a text string as a literal value. For example, the following will create a single directory named 'Documents and Settings'
user@host:~$ mkdir 'Documents and Settings'
Without quotes, the same command would create three directories: Documents
, and
, and Settings
user@host:~$ mkdir Documents and Settings
Either single-quotes (apostrophes) or double-quotes (quotation marks) can be used to enclose a literal string:
user@host:~$ echo 'Jimmy says "Hello"'
Jimmy says "Hello"
user@host:~$ echo "Jimmy's friend does not respond"
Jimmy's friend does not respond
However, if a double-quoted string encloses a special character, such as the dollar-sign that denotes a variable, the shell will expand the variable to its value:
user@host:~$ some_number=42
user@host:~$ echo 'There are $s bottles of beer'
There are $some_number bottles of beer
user@host:~$ echo "There are $some_number bottles of beer"
There are 42 bottles of beer
Vital to know for multi-line strings:
cat > stuff.html <<EOF
<html>
<h1>
<a href="http://example.com">An example</a>
</h1>
</html>
EOF
Main article: Introduction to command syntax and execution
At a glance:
Many commands take space-separated arguments. For example, the mkdir takes in one or more arguments and will create a new directory for each one:
user@host:~$ mkdir apples oranges 'Documents and Settings'
Some programs, such as cat
, grep
, and wc
, will interpret arguments as referring to names of existing files to open and process:
wc existing.file.txt
Contrast this to echo
, which does not interpret its arguments as filenames:
user@host:~$ echo echo echo "Ok enough with the echoes"
echo echo Ok enough with the echoes
user@host:~$ echo filename.txt
filename.txt
Many commands have options (also referred to as flags), to allow the user to customize the functionality. For example, curl takes in a URL as an argument and will download the file at that URL to standard output. However, the user can use the --output
option to specify a filename to save to:
user@host:~$ curl http://www.example.com --output myfile.txt
Many command options have shorthand aliases. For curl, --output
and --silent
can be referred to as -o
and -s
, respectively:
user@host:~$ curl http://www.example.com --output myfile.txt --silent
user@host:~$ curl http://www.example.com -o myfile.txt -s
Every command has its own origin story, and consequently, its own options and arguments and rules of behavior. Do not think that the behavior and options of one command translates to another:
user@host:~$ curl -vo test.html "www.example.com"
user@host:~$ grep -vo test.html "www.example.com"
You will never be able to memorize all the combinations. But remember what commands can do, and then look up the documentation.
Use man
, followed by the name of a command, to retrieve its documentation. You may find it easier just to do a Google search for a command's name.
user@host:~$ man grep
Main article: Pipes and Redirection
At a glance:
user@host:~$ cat file.txt | sort
user@host:~$ sort file.txt > sorted.txt
user@host:~$ head -n 10 a.txt >> all.txt
user@host:~$ head -n 10 b.txt >> all.txt
Main article: Variables and command substitution
At a glance:
user@host:~$ some_val="Some value"
user@host:~$ echo "This is $some_val"
This is Some value
user@host:~$ nums=$(seq 1 3)
user@host:~$ echo "My favorite numbers: $nums"
My favorite numbers: 1
2
3
user@host:~$ x=$((99 + 1))
user@host:~$ y=$(( 10 + x))
user@host:~$ echo $y
110
Main article: For and Read-While Loops
At a glance:
user@host:~$ for item in $items;
do
echo $item
done
user@host:~$ for x in $(seq 1 100);
do
echo $x
done
user@host:~$ while read line
do
echo $line
done < file
Main article: Running shell scripts from Bash
At a glance:
user@host:~$ nano somefile.sh
user@host:~$ bash somefile.sh
user@host:~$ chmod a+x somefile.sh
user@host:~$ ./somefile.sh
Main article: Basic conditional branching with if-then statements
At a glance:
user@host:~$ if [[ $text1 == $text2 ]]
then
echo "These are equal"
fi
user@host:~$ if [[ $text1 == $text2 ]]
then
echo "These are equal"
else
echo "These are not equal"
fi
user@host:~$ if [[ $text1 == $text2 ]]
then
echo "These are equal"
elif [[ $text1 > $text2 ]]
then
echo "$text1 alphabetically precedes $text2"
else
echo "These are not equal"
fi
user@host:~$ c=10
user@host:~$ while [[ $c -gt 0 ]]; do
echo "The countdown is $c"
c=$((c - 1))
done
user@host:~$ while [[ 1 -eq 1 ]]; do
echo 'FYI, 1 is still equal to 1'
done
If you are reading this and are currently a Stanford student: Every time you close your laptop and re-open it. Or switch away from Terminal to check Facebook. Or switch away from one Terminal window to another Terminal window. Or step away for 10 seconds to get a drink of water. Or blink for longer than 5 seconds…
– The very next command you should run at the Terminal prompt should be:
hostname
Does it include corn
and stanford.edu
? If not, then you may be messing with the files and directories of your own computer, which is not required or recommended for the scope of the CompCiv class.
Top-line summary: For the purposes of this class, never, ever run rm -rf
in an automated script. In fact, just to be safe, don't even run it manually, especially on your personal computer. If you need to remove a directory, use rmdir
, which will error out if that directory is not empty.
Remember the story about Pixar wiping out all of Toy Story 2 with rm -rf *
?
rm -rf
tells the Unix shell to remove files, by force, and recursively (i.e. any subdirectories in a target directory), without asking questions or confirmation.
If Pixar could accidentally rm -rf
a movie with a production budget of $90 million, you should assume that you, a novice user of Unix, will do just as much damage to yourself. rm -rf
is a heartless, nihilistic command that does not care what your directory contains – whether it's just your homework, every photo and document you've ever created, or a blockbuster animated movie – before completely obliterating it.
Here are a few of the ways you could screw up when running rm -rf
, either manually or in an automated script:
For the homework, there will rarely be steps that require you to delete anything, even a single file, via an automated script. And there should never be a time when you need to run rm -r
, nevermind rm -rf
– email me first before you think to include it any script.
If you are rm
'ing files manually, at the very least, take a second and execute:
hostname && pwd && whoami
Do any of those indicate that you are on your own personal computer (rather than Stanford's shared computing, or a cloud server)? Then maybe stop what you are doing.
Very little in this course requires you to be in a rush. So before you do any major task, stop and do these steps:
Run hostname
to see what machine you're on. If you are on Stanford's Farmshare, the response should be something like:
corn10.stanford.edu
Anything else, and you're probably operating from your own OS X or Linux machine.
Run whoami
to see who you're logged in as. If you're on corn.stanford.edu
, the response will be your SUnet ID.
Run pwd
(print working directory) to see where in the file system you are. If you've just logged into corn.stanford.edu
, you should be in your home directory:
/afs/.ir/users/y/o/your_sunet_id
Run ls
to list the files in the directory
By default, your bash prompt on corn.stanford.edu
looks something like this:
dun@corn24:~$
Perhaps you'd like it to be a little more obvious about what system you're currently on. To customize your corn.stanford.edu
prompt, use nano
to open and edit the file, ~/.bashrc
Once inside ~/.bashrc
, go to the bottom of the file and add this variable assignment:
PS1='[GO CARDNIAL (°<°)]\u@\h:\w\$ '
(if you read through ~/.bashrc
, you'll see that PS1
is assigned a value earlier in the file. Your new line will overwrite that value, so if you don't like what you've done, just delete your line from ~/.bashrc
)
After exiting nano
and saving your changes, you have to restart your shell in order for the changes to take effect. You can either just logout and log back in, or run this command:
source ~/.bashrc
Your shell should now be updated with this prompt:
[GO CARDNIAL (°<°)]dun@corn25:~$
If you want something a little more emotive, check out this list of Japanese Kaomoji, and re-open ~/.bashrc
and re-edit your variable assignment of PS1
accordingly:
PS1='(BRING IT!> ლ(ಠ_ಠლ) \u@\h:\w\$ '
Like colors? Follow the patterns in this guide.
If you're adding lots of colors and emoji to your prompt, it may be easier to break it up into different variables, and then combine them into PS1
For example:
PS_SHRUGGY_GUY='¯\_(ツ)_/¯'
PS_HEART='♡'
PS_STUFF='\u@\h:\w\$ '
# Colors
BIRed='\e[1;91m'
BIPurple='\e[1;95m'
Black='\e[0;30m'
## All together
PS1="$BIPurple$PS_SHRUGGY_GUY$BIRed$PS_HEART $Black$PS_STUFF"
Do you find yourself typing over the prompt (i.e having a line-wrapping issue) because you loaded it with Japanese characters? Check out this solution on StackOverflow
In descending order of importance. Note that these only work at the standard prompt. If you're in a program like the nano text editor, then you have a whole different set of shortcuts to learn.
This breaks/kills whatever program or command that you're currently running. If you ever get stuck in a loop, or a berzerking program, or just don't know why your prompt isn't responding to any input, hit Ctrl-C a few times.
This will attempt to autocomplete the name of a file or program based on what you've typed in so far. If there are multiple possibilities, hitting Tab twice will list them.
This will cycle backwards through your history of commands. Handy for re-running a previous command in which you want to change one variable/typo.
The opposite of Up.
When at the prompt, this shortcut will bring your cursor to the beginning of the current line. Handy for when you need to fix a typo before hitting Enter.
The opposite of Ctrl-A; this brings you to the end of the current line.
This clears the screen, handy for after a program has just dumped a bunch of data into standard output.
If you've just executed a long-running process, Ctrl-Z will suspend it and return you to the prompt. At this point, you can type in bg
to have the process run in the background. Or use fg
to have the process continue running in the foreground.
If you are at the standard prompt, this will cause you to log out. If you're typing into a program via standard input (e.g. mail
), and hitting Enter only create new lines, use Ctrl-D to exit back into the standard prompt.
How to get around the Unix filesystem.
pwd
to show the name of the current directoryls
to list files in the current directorycd
to change directorymkdir
to create directoriescd ~
- Jump to your home directory.cd /
- Jump to the root directory, (something that you should almost never have to do)cd ..
- Move to the parent directorycd ../..
- Move up through two directoriesmkdir -p /tmp/hello/this/is/fun
- Create a new directory and all of its parent directories as necessary (i.e. the -p
option)cd -
, equivalent to cd $OLDPWD
, i.e. it returns you to whatever directory you were previously at.Note: These instructions are for OS X/Linux users.
If you have a file on your own computer that you'd like to move to a remote computer, such as to corn.stanford.edu
, you can use the scp file transfer program. When running scp
, you'll be asked to enter your SUnet password (as if you were just SSHing in):
# usage: scp account@remote.machine.com:/remote/path local_path
scp your_sunet@corn.stanford.edu:~/some/path/data.txt ~/Downloads/data.txt
# usage: scp local_path account@remote.machine.com:/remote/path
scp ~/Uploads/data.txt your_sunet@corn.stanford.edu:~/some/path/data.txt
Before 2012, students were given tcsh as their "default shell". Afterwards, students were given bash. This code examples in this course assume that you will be using bash. You can email the Farmshare IT Group to have your default shell be changed to bash.
When you've made changes to your compciv
repo (i.e. project folder on corn.stanford.edu
), here are the git commands to add, commit, and push changes to your master repo on Github.com:
# (assuming you're in the compciv folder)
git add --all
git commit -m 'Changing my code for fun'
git push
More information:
Note: I've deprecated this section. It will still "work", but it's a little inconvenient on corn.stanford.edu
and may require you to re-run and re-configure the ssh-agent
(yes, it's as boring as it sounds) every time you log back into corn.stanford.edu
. These instructions will work from your personal computer, if for some reason you are cloning and pushing from your own computer instead of corn.stanford.edu
The whole process we undertook to generate a SSH key was so that we could connect to transfer files to Github from corn.stanford.edu
…
You can verify if you're authenticated by running the following command when logged into corn.stanford.edu
:
ssh -T git@github.com
# response from Github:
# Hi dannguyen! You've successfully authenticated, but GitHub does not provide shell access.
If you get a Permission denied (publickey).
, it means you have to re-authenticate (but you shouldn't have to regenerate a keypair). You can re-authenticate with these steps (this is assuming you placed your key in ~/.ssh/compciv_id_rsa
):
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/compciv_id_rsa
# After this command, you'll be asked to enter your passphrase... this is NOT
# the same as your password for SUnet or for Github
If you've forgotten your passphrase, you can always repeat the keypair generation steps from the beginning. Just delete the existing ~/.ssh/compciv_id_rsa