introduction to the unix command-line
UNIX was an operating system developed at AT&T Bell Labs in the 1960s through the 1980s (originally named UNICS from Uniplexed Information and Computing Service which later became UNIX).
https://www.youtube.com/watch?v=tc4ROCJYbm0
GNU/Linux, MacOSX, and Android are all based on ideas and specifications created by UNIX.
https://en.wikipedia.org/wiki/File:Unix_history-simple.svg
UNIX was originally built for large mainframe computers that many people would use at the same time.
- teleprinters printed program output on paper
- terminals displayed output on a CRT monitor
Neither device had processing power of their own.
Connected to the mainframe over cables or by telephone.
Every program on a UNIX system can read input from the standard input device (stdin) and write to standard output (stdout).
By default, stdin comes from the keyboard and stdout gets "printed" to the graphical display.
The UNIX operating system is a collection of programs, each with a special role:
- kernel
- shell
- utilities
mediate access between user programs and system resources
- CPU scheduling
- I/O to computer hardware
- memory
Programs request resources by making a syscall.
A shell is a computer program that can execute other programs from a text-based interface.
In a text-based interface, you interact with a program completely from the command-line with text commands and text output.
Most modern shells are strongly influenced by the first UNIX shells.
- thompson shell - Ken Thompson 1971
- pwb (mashey) shell - John Mashey 1975
- bourne shell - Stephen Bourne 1977
- c shell (csh) - Bill Joy 1978
- tcsh - Ken Greer and Mike Ellis 1983
- korn shell - David Korn 1983
- bourne again shell (bash) - Brian Fox 1987
- almquist shell (ash) - Kenneth Almquist 1989
- debian almquist shell (dash) - Herbert Xu 1997
incomplete list of popular or influential shells
Any distribution of UNIX will come with dozens of other programs that perform narrow single-purpose tasks.
The available utilities on a given system vary widely but some utilities are very common.
For example, there is a command to make new directories and another to move files.
- portable to many kinds of hardware
- consistent conventions
- vast software ecosystem
- text!
- wifi routers
- dsl and cable modems
- raspberry pi, beaglebone, nvidia jetson
- android phones
- linux laptop or desktop
- Mac OSX computer
- web server
You can take your command-line skills with you to all of these platforms and more!
To remotely access a UNIX system, you can use the same command-line tools and interface that you use locally. You can remotely access devices without a display.
Text is easy to read so you can poke around more easily to figure out what's going on. Many aspects of computer programming involve shuffling text around. UNIX excels at these kinds of tasks.
The unix philosophy is a set of design principles for how programs relate to each other.
- each program should do one thing well
- the output of a program can become the input of another
Unix Programming Environment 1984 Brian Kernighan and Rob Pike
bash is a popular shell for UNIX-like systems.
Open up a bash shell for the next sections to follow along.
If you're not sure which shell you're in, type:
echo $SHELL
If you're in bash, you sould see something like:
/bin/bash
You can use the ls
command to show all the files
in the current directory.
Type ls
and you should see something like:
~ $ ls
doc media notes.txt projects
By default, ls
lists files from the current directory.
You can list files from another directory by
giving ls
an argument. An argument is just
another piece of text after the ls
.
For example, to list the files in /
(the root)
we can do:
~ $ ls /
bin etc lib media proc sbin sys var
boot home lib64 mnt root selinux tmp vmlinuz
dev initrd.img lost+found opt run srv usr
In this example, ls
is the command and /
is the argument.
Commands can have multiple arguments separated by spaces or no arguments.
To display the current directory, you can use the
pwd
command:
$ pwd
/home/substack
pwd stands for print working directory.
To change the current working directory, use the
cd
command. The cd
command takes a single
argument: the directory to move to.
After changing the current directory, list the
files again with ls
.
~ $ ls
doc media notes.txt projects
~ $ cd media
~/media $ ls
3d audio avatars vector warp
~/media $ cd warp
~/media/warp $ ls
mac.sh* mac_startup.mp3 mac_warped.mp3 watch.js
Mac Startup-i9qOJqNjalE.mp4 mac_startup.wav mac_warp.mp3
There are some special directories:
..
- the parent directory.
- the current directory~
- your home directory
To navigate back up to the parent directory, do
cd ..
.
~/media/warp $ cd ..
~/media $
You can also list the parent directory without
changing the current directory by doing ls ..
:
~/media $ ls ..
doc notes.txt media projects
You can add paths after ..
too:
~/media $ ls ../projects/workshops
computers.markdown unix.markdown
Or ls .
is the same as ls
:
~/media $ ls .
3d audio avatars vector warp
Jump back to your home directory at any time by
typing cd
with no arguments.
cat was originally written to concatenate all the files from its arguments:
~/doc $ cat beep.txt boop.txt
BEEP
BOOP
but it also a handy way to display single text files on the command-line:
~/doc $ cat beep.txt
BEEP
Copy a file to another directory or file name. You can copy a single file to make a new duplicate file:
~/doc $ ls
a.txt
We can copy a.txt to b.txt:
~/doc $ cp a.txt b.txt
Now there are 2 identical files, a.txt
and b.txt
:
~/doc $ ls
a.txt b.txt
You can copy a file or a directory too. Here we'll
copy a.txt
to the directory called wow
:
~/doc $ mkdir wow
~/doc $ ls
a.txt b.txt wow
~/doc $ cp a.txt wow
now wow/
has an a.txt
file in it:
~/doc $ ls wow
a.txt
You can copy to a specific destination file:
~/doc $ cp a.txt wow/whatever.txt
~/doc $ ls wow
a.txt whatever.txt
You can even copy multiple files at once to a new place:
~/doc $ mkdir xyz
~/doc $ cp a.txt b.txt xyz/
~/doc $ ls xyz
a.txt b.txt
The last argument is the destination file or directory and the other arguments are the source files.
If you have a directory full of files and
directories you want to copy to a new place, you
can use cp -r
to recursively copy a directory
and all its subdirectories to a new location:
~/doc $ mkdir xyz/123
~/doc $ cp a.txt xyz/123/
~/doc $ cp -r xyz newxyz
~/doc $ ls newxyz/
123 a.txt b.txt
~/doc $ ls newxyz/123
a.txt
Likewise, there is a -R
for the ls
command that recursively lists
subdirectories:
~/doc $ ls -R newxyz
newxyz:
123 a.txt b.txt
newxyz/123:
a.txt
The mv
command is used to rename and overwrite
files and directories.
To rename a file, set the first argument to the original file name and the second argument to the new file name or destination directory.
We can rename a.txt
to be pigeon.txt
:
~/doc $ mv a.txt pigeon.txt
~/doc $ ls
b.txt newxyz pigeon.txt xyz
Or we can move a file to a new directory:
~/doc $ mv pigeon.txt xyz
~/doc $ ls xyz
123 a.txt b.txt pigeon.txt
We can rename directories just the same as files:
~/doc $ mv xyz woo
~/doc $ ls
b.txt newxyz woo
~/doc $ ls woo
123 a.txt b.txt pigeon.txt
To make a new directory, just execute the mkdir
command with a list of new directory names to make
as arguments:
$ mkdir hooray
and now a new directory called hooray
exists.
You can create multiple directories at once:
$ mkdir one two
and now two new directories, one
and two
,
exist.
Suppose we want to make the following nested directory structure:
foo/
bar/
baz/
qrs/
Instead of doing:
~ $ mkdir foo foo/bar foo/bar/baz foo/bar/qrs
We can just do:
~/doc $ mkdir -p foo/bar/baz foo/bar/qrs
and the necessary parent directories foo/
and
foo/bar/
will be created automatically.
There is a handy syntax built into bash for expanding patterns that would be repetitive to type out by hand.
Instead of doing something like:
~/doc $ mkdir -p foo/bar/baz foo/bar/qrs
we can use a list of items between curly braces:
~/doc $ mkdir -p foo/bar/{baz,qrs}
which expands to the same command as before.
To prove this you can use echo
to see what the
expansion is:
~ $ echo mkdir -p foo/bar/{baz,qrs}
mkdir -p foo/bar/baz foo/bar/qrs
The items that a brace expansion generates are separated by spaces as if you had typed out those words by hand.
You can have as many items as you like in a list:
~ $ echo robot-{one,two,three,four}-x
robot-one-x robot-two-x robot-three-x robot-four-x
With brace expansions, you can have multiple expansions:
~/doc $ echo robot/{c3po,r2d2}/{sound.mp3,info.txt}
robot/c3po/sound.mp3 robot/c3po/info.txt robot/r2d2/sound.mp3 robot/r2d2/info.txt
You can even nest the expansions!
~/doc $ echo x-{wing,b{ee,oo}p}
x-wing x-beep x-boop
It can be tedious to type out numerical lists by hand.
Brace expansions can help with that:
~/doc $ echo wow{1..10}
wow1 wow2 wow3 wow4 wow5 wow6 wow7 wow8 wow9 wow10
and you can even specify an amount to skip:
~/doc $ echo img{0..100..10}
img0 img10 img20 img30 img40 img50 img60 img70 img80 img90 img100
To remove a file, just do:
~/doc $ rm b.txt
You can remove multiple files at once:
~/doc $ rm newxyz/a.txt newxyz/b.txt
and you can remove entire directories including subdirectories with:
~/doc $ rm -r newxyz
Be very careful with -r
. You might accidentally
delete much more than you meant to delete!
The wc
command computes the number of lines,
words, and bytes in a file:
~ $ wc notes.txt
3 7 35 /home/substack/notes.txt
To see each field independently, you can use
different options: arguments that start with a -
or --
followed by a letter or word.
To get just the word counts, we can use -w
:
~ $ wc -w notes.txt
7 notes.txt
To get just the number of lines in a file, use -l
:
~ $ wc -l notes.txt
3 notes.txt
To get just the number of bytes in a file, use -c
:
~ $ wc -c notes.txt
35 notes.txt
If you don't specify a file, wc
will read from
stdin. Type Ctrl+D (^D) to end the input.
~ $ wc -l
one
two
three
four
^D
4
All of these command options are a lot to remember!
You can pull up documentation at any time in your
shell by typing man foo
for any command foo
.
For example to read up on all the options you can
give to the wc
command, do:
~ $ man wc
The help page will open up in your $PAGER
. Type
q
to exit back to your shell.
Options (also called flags or switches) are
special arguments that start with a -
or --
followed by a letter or word.
Generally speaking, they are distinct from other arguments in that their order usually doesn't matter. For example:
grep -i wow
is the same as
grep wow -i
where -i
just informs the grep
command to
perform a case-insensitive search.
Sometimes options have a value that follows:
head -n 1
means that -n
has the value 1
.
Sometimes you can omit the space:
head -n1
but each program individually decides how to interpret its arguments.
Paths that start with .
or ..
are relative paths.
Paths that start with /
are absolute paths.
Relative paths are resolved according to the current working directory:
~/doc $ cat ../media/warp/mac.sh
#!/bin/bash
youtube-dl 'https://www.youtube.com/watch?v=i9qOJqNjalE'
ffmpeg -i *.mp4 -vn mac_startup.wav
sox mac_startup.wav mac_warp.mp3 chorus 0.6 0.9 25 0.9 1 8 -s \
echos 0.8 0.7 40 0.25 63 0.3 phaser 1 0.7 3 0.7 0.5 -t
play mac_startup.wav
Absolute paths are the same no matter what the current working directory is:
~/projects/workshops $ cat /etc/issue
Debian GNU/Linux 7 \n \l
The echo command just prints text from its arguments:
~ $ echo wow cool
wow cool
This is not very useful by itself, but becomes useful when combined with redirects and pipes.
Using the >
character, you can write the output
of a command to a file.
For example, to make a new file greetings.txt
with the contents "ahoy thar", we can do:
~ $ echo ahoy thar > greetings.txt
and to print the contents of greetings.txt, use cat
:
~ $ cat greetings.txt
ahoy thar
You can redirect the output of any program to a file:
~ $ ls / > list.txt
The >
redirect operator will overwrite a file
with new contents if it already exists.
There is a >>
operator that appends to the end
of a file if it already exists:
~ $ echo wow > cool.txt
~ $ ls >> cool.txt
~ $ cat cool.txt
wow
cool.txt
doc
media
notes.txt
projects
You can read a file into the stdin of a program
with <
.
Remember that if wc
doesn't get a file as an
argument, it will read from stdin. We can load a
file in to wc
with <
instead:
~ $ wc -c < notes.txt
35
The last but most important kind of redirect is
the pipe operator |
.
With |
you can feed the output of one program to
the input of the next.
For example, the ls -1
command will list files,
one per line, to stdout. The wc -l
command,
meanwhile, will count the number of lines.
By piping these two programs together, we can count the number of files and subdirectories in a directory:
~ $ ls -1 | wc -l
5
and indeed, there are five files and subdirectories in this directory:
~ $ ls -1
cool.txt
doc
media
notes.txt
projects
You can chain together commands with |
as much
as you like.
Here's an example using two new commands curl
and sed
that will fetch Moby Dick from Project
Gutenberg and count the number of occurences of
"whale", case-insensitive:
~ $ curl -s http://www.gutenberg.org/cache/epub/2701/pg2701.txt
| sed -r 's/\s+/\n/g' | grep -i whale | wc -l
1691
We can even save that number of a file. Just add
> whale_count.txt
to the end of the pipeline:
~ $ curl -s http://www.gutenberg.org/cache/epub/2701/pg2701.txt |
sed -r 's/\s+/\n/g' | grep -i whale | wc -l > whalecount.txt
Here's a breakdown of each part of the pipeline and what it does:
curl -s http://www.gutenberg.org/cache/epub/2701/pg2701.txt
fetches Moby Dick from Project Gutenberg and prints the results to stdout.
sed -r 's/\s+/\n/g'
converts all whitespace (tabs, spaces, newlines) into newlines.
This means that each word gets its own line:
~ $ echo one two three beep boop | sed -r 's/\s+/\n/g'
one
two
three
beep
boop
grep -i whale
filters the output so that only lines that contain
the word "whale" will be shown. -i
makes the
search case-insensitive.
For example if we have a file tale.txt
:
Wow
such
a
whale.
A
whale
of
a
WHALE!
then our grep command will show:
~ $ grep -i whale < tale.txt
whale.
whale
WHALE!
wc -l
counts the number of lines from stdin and prints the result.
The head command prints the first part of a file.
If a file isn't given, head
reads from stdin.
Read the first 3 lines of a file with head -n3
:
$ head -n3 mobydick.txt
The Project Gutenberg EBook of Moby Dick; or The Whale, by Herman Melville
This eBook is for the use of anyone anywhere at no cost and with
Read the first 20 bytes of a file with head -c20
:
~ $ head -c20 mobydick.txt
The Project Guten
The tail command prints the last part of a file.
If a file isn't given, tail
reads from stdin.
Read the last 4 lines of a file with tail -n4
:
~ $ tail -n4 mobydick.txt
This Web site includes information about Project Gutenberg-tm,
including how to make donations to the Project Gutenberg Literary
Archive Foundation, how to help produce our new eBooks, and how to
subscribe to our email newsletter to hear about new eBooks.
Read the last 9 bytes of a file with tail -c9
:
~ $ tail -c9 mobydick.txt
eBooks.
If you need a handy text calendar, just type cal
:
~ $ cal
December 2014
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
You can show the current, previous, and next month:
~ $ cal -3
November 2014 December 2014 January 2015
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 1 2 3 4 5 6 1 2 3
2 3 4 5 6 7 8 7 8 9 10 11 12 13 4 5 6 7 8 9 10
9 10 11 12 13 14 15 14 15 16 17 18 19 20 11 12 13 14 15 16 17
16 17 18 19 20 21 22 21 22 23 24 25 26 27 18 19 20 21 22 23 24
23 24 25 26 27 28 29 28 29 30 31 25 26 27 28 29 30 31
30
Or you can show a whole year:
~ $ cal 2015
2015
January February March
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 3 1 2 3 4 5 6 7 1 2 3 4 5 6 7
4 5 6 7 8 9 10 8 9 10 11 12 13 14 8 9 10 11 12 13 14
11 12 13 14 15 16 17 15 16 17 18 19 20 21 15 16 17 18 19 20 21
18 19 20 21 22 23 24 22 23 24 25 26 27 28 22 23 24 25 26 27 28
25 26 27 28 29 30 31 29 30 31
April May June
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 3 4 1 2 1 2 3 4 5 6
5 6 7 8 9 10 11 3 4 5 6 7 8 9 7 8 9 10 11 12 13
12 13 14 15 16 17 18 10 11 12 13 14 15 16 14 15 16 17 18 19 20
19 20 21 22 23 24 25 17 18 19 20 21 22 23 21 22 23 24 25 26 27
26 27 28 29 30 24 25 26 27 28 29 30 28 29 30
31
July August September
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 3 4 1 1 2 3 4 5
5 6 7 8 9 10 11 2 3 4 5 6 7 8 6 7 8 9 10 11 12
12 13 14 15 16 17 18 9 10 11 12 13 14 15 13 14 15 16 17 18 19
19 20 21 22 23 24 25 16 17 18 19 20 21 22 20 21 22 23 24 25 26
26 27 28 29 30 31 23 24 25 26 27 28 29 27 28 29 30
30 31
October November December
Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa
1 2 3 1 2 3 4 5 6 7 1 2 3 4 5
4 5 6 7 8 9 10 8 9 10 11 12 13 14 6 7 8 9 10 11 12
11 12 13 14 15 16 17 15 16 17 18 19 20 21 13 14 15 16 17 18 19
18 19 20 21 22 23 24 22 23 24 25 26 27 28 20 21 22 23 24 25 26
25 26 27 28 29 30 31 29 30 27 28 29 30 31
To print the date, just do:
~ $ date
Sat Dec 27 20:43:13 PST 2014
You can format the date however you like:
~ $ date +'%Y-%m-%d %H:%M:%S'
2014-12-27 20:45:07
Check out the manual page (man date
) for more info about what options are
available for date strings.
Sometimes it's handy to break long lines into shorter lines.
We can use the fold command to break some text at 30 characters:
~ $ head -n250 mobydick.txt | tail -n3 | fold -w 30
can see a whale, for the first
discoverer has a ducat for hi
s pains....
I was told of a whale taken ne
ar Shetland, that had above a
barrel of
herrings in his belly.... One
of our harpooneers told me tha
t he caught
or to break on spaces instead, use -s
:
~ $ head -n250 mobydick.txt | tail -n3 | fold -sw 30
can see a whale, for the
first discoverer has a ducat
for his pains....
I was told of a whale taken
near Shetland, that had above
a barrel of
herrings in his belly.... One
of our harpooneers told me
that he caught
curl is a handy little tool for making HTTP requests.
Here's a simple snippet to fetch my most recent RSA public key from github, wrapping the output to 75 character lines:
~ $ curl -s https://github.com/substack.keys | tail -n1 | fold -w75
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAEAQC7wF3cwpH+NVG+qNz0PLjEg9IqaNyXeeITme9
fksfJx/rTyoFAWW+JrJVKLPNBCe63JYvp3pTvPqJRg/8hEb/+uFlIIzUNhHAUSaS1mmKgnTHbb+
1d8CkFAZiZnDhFOKRkEXh5R9F9htNQVIjyzD3XL/H69mb8YzICItq/9klVTZ66s1thp7r3V5+qE
hbLB4yH6stXyuj2SZiMS+CJeVBJ8Pf/CCUH66NK2o7l1zliJwme+UJry1RtxWQBfEChj9qe36B/
bR3HACtx6ANMdYJsOxZm0znUjn/XJ9jxy22nVJY5otwZNeIZSSyA1lZB2mZRzTTWzPPx62VWdgH
eQdOmnqBP0YWpxPBSMJwn4kFt6aGImrm7WTU5sHwqqxRgNvcrecxPWgbdLcV+x/OWF5bug3s096
AWcP4wQI101w7QtI3cc5+JKHSGssuY17jyyNaHttE7GafBu3pbK93YolgNAMyYUHVicgK+uY6o+
sH4gcRx+RyQ4OkO7Js49wJi0AXPGhp5QRmIFpua/vVzhMTwMhqW+6luWgfPeAVqn95erc49cY+W
2B83ZgaDVSuRfDafVCSjUl+oXG/1KxzP2F/ZhGmNGmBRnF5N4OLHW6/KtVgxCpf3+1bcgye+yiq
NQuM5/NNWZRw3NJhk0XEppd5Ai4JpvguDLhWZ19/+XEvFj9kwKRMRbxf1M7hWDutAE46sQc9x4M
135M/SyuHW9asHBDCJPgD3nBAjYpMV0fQxIbcNiYWF+JsH6NzhRpLnsTNUvsfUcC/FQqX3VD0Xu
IEoYmKwDesv6PU60pQNEi6p4u+PnFHS/vvRASYLo/4s+99GQDWxqzi0jjYVWheQW9RLnTU+ghud
A+xPp7CK/tH8/RAutDdk3k0HdsNTsjHFN/HvM23UIHOpuY07yohayQididHt023IAZdys6m2daQ
RUKXM8cfaFdQqoj/vaby7pxBPWzO6tuXy1tI6gQ+nolZaXQfXUBHF1uBXo1UQI0dp8J5tCppty6
NvXmvv90PBGVXOlplyhXB9q0JXBInidATeT8zlgM4Iq1X6ZVlXN2OIU5CiWVA1NYmf05709e6SK
P0kK2oh19gA+qg1oPOw0WTpZGKz/9NCCw2ywK2/yNJRWuIbSE4RAv6N8v7qtPObwAU5Lohj8oQV
yC/bbLF6VuVJo6V/nfvP+EJKtsXlBBPBzdsmV1hikkGLJx7Up1s7WTZCwSeSGFPXCe7RdElz2mQ
YB6dwEbhaGl48MhuiIeER7KZqzQFOu74G0u5tyyCUeEc90BkeUcf/EhrxfS8R9ZRJ9ce7IpYQ4+
9wTBKFzVc1HinCSUwJTu7m+UHLaaNbK+WCIF+2fFvM1IJmTh2pWSMb
You can search for patterns in files or from stdin
with the grep
command.
The first argument is the pattern to search for as a regular expression.
Regular expressions are a language for pattern matching.
Here we can search for all lines matching "whaling" or "fishing":
~ $ grep -iE '(whal|fish)ing' mobydick.txt | tail -n5
Equatorial fishing-ground, and in the deep darkness that goes before the
the whaling season? See, Flask, only see how pale he looks--pale in the
preliminary cruise, Ahab,--all other whaling waters swept--seemed to
fixed upon her broad beams, called shears, which, in some whaling-ships,
years of continual whaling! forty years of privation, and peril, and
Check out the other workshop about regular expressions to learn more!
Sometimes it's useful to include the output of a program in the arguments list of another.
For example with the date command we can print the current year:
date +%Y
and we can use this value in a message with echo:
~ $ Greetings from the year `date +%Y`.
Greetings from the year 2014.
With $((...))
expressions, you can do simple
arithmetic on the command line!
~ $ echo $((4*5+1))
21
I wouldn't go overboard with this feature, but it's handy sometimes.
Environment variables are defined by the shell and shell scripts.
To list the current environment variables, type
export
:
~ $ export
declare -x DISPLAY=":0"
declare -x HOME="/home/substack"
declare -x HUSHLOGIN="FALSE"
declare -x LANG="en_US.UTF-8"
declare -x LD_LIBRARY_PATH="/home/substack/prefix/lib:/usr/local/lib:/usr/lib/x86_64-linux-gnu:/usr/lib:/lib64:/lib"
declare -x LIBGL_DRIVERS_PATH="/usr/lib/i386-linux-gnu/dri:/usr/lib/x86_64-linux-gnu/dri"
declare -x LOGNAME="substack"
declare -x MAIL="/var/mail/substack"
declare -x OLDPWD="/home/substack/projects/workshops"
declare -x PATH="/home/substack/prefix/bin:/usr/local/bin:/usr/bin:/bin:/sbin:/usr/sbin:/usr/local/games:/usr/games"
declare -x PREFIX="/home/substack/prefix"
declare -x PWD="/home/substack"
declare -x ROXTERM_ID="0x43962f0"
declare -x ROXTERM_NUM="15"
declare -x ROXTERM_PID="2521"
declare -x SHELL="/bin/bash"
declare -x SHLVL="3"
declare -x TERM="xterm"
declare -x USER="substack"
declare -x WINDOWID="8684328"
declare -x WINDOWPATH="7"
declare -x XAUTHORITY="/home/substack/.Xauthority"
You can use any environment variable by refering to its $NAME
.
For example to print the value of $HOME
do:
~ $ echo $HOME
/home/substack
You can use environment variables in any command:
~ $ ls /home/$USER
doc media notes.txt projects
To define your own environment variable, just put its name followed by an equal sign (with no spaces) followed by its value:
~ $ ANIMAL=cats
~ $ echo $ANIMAL
cats
Environment variables are almost always capitalized to distinguish them from variables in shell scripts but lower-case variables work too.
If you want to use characters like <
or >
in
the arguments to a program, you will need to use
quotes so that the shell doesn't try to interpret
them.
For example, to echo the string <b>wow</b>
we
can use single quotes:
~ $ echo '<b>wow</b>'
<b>wow</b>
Double quotes are similar but environment variables and backticks will be interpolated in-place (replaced with their value):
~ $ echo "There's no place like $HOME."
There's no place like /home/substack.
~ $ echo "So long `date +%Y`..."
So long 2014...
~ $ echo "So long `date +%Y`... next stop $((`date +%Y`+1))"'!'
So long 2014... next stop 2015!
You will also need to use quotes if one of the arguments you want to give has a whitespace character in it, because whitespace is otherwise used to split arguments.
Whenever you find yourself typing the same sequence of commands several times, consider making a script!
Just put the commands you would normally type into
a file and add #!/bin/bash
to the top of the
file:
#!/bin/bash
mkdir wow
cd wow
echo "yay" > zing.txt
Now make your script file executable:
~ $ chmod +x yourscript.sh
And now you can do:
~ $ ./yourscript.sh
to run the commands from your file!
When you execute a script with arguments on the
command-line, special environment variables $1
,
$2
, $3
... will be defined for each argument.
For example, if our script is:
#!/bin/bash
echo first=$1
echo second=$2
Then we print out the first and second arguments:
~ $ ./yourscript.sh beep boop
first=beep
second=boop
There is a special variable $*
that contains all
the arguments separated by spaces. For a script
of:
#!/bin/bash
echo The arguments are: $*
And now we can get at all the arguments in one place:
~ $ ./args.sh cats dogs ducks lizards
The arguments are: cats dogs ducks lizards
There is a special environment variable called $PATH
:
~ $ echo $PATH
/usr/local/bin:/usr/bin:/bin:/sbin:/usr/sbin:/usr/local/games:/usr/games
This variable contains a list of places separated
by :
that bash will look when you type a
command.
If you put an executable file in one of the
directories in your $PATH
, you can make your own
commands without needing to specify a relative or
absolute path!
/usr/local/bin
is the customary place to put
system-specific scripts that are not managed by
your system distribution. If you do:
~ $ sudo cp yourscript.sh /usr/local/bin
Then you'll be able to type yourscript.sh
from
any directory on the command-line!
You can rename that command that you type by renaming the file:
~ $ sudo mv /usr/local/bin/{yourscript.sh,whatever}
and now the command is called whatever
.
There is a special bash script called ~/.bashrc
that runs whenever you start bash. You can edit
this file to set up aliases, environment
variables, and run commands when you start a new
terminal session.
At the bottom of your ~/.bashrc
file, try adding
a command:
echo Greetings $USER. Nice to see you again.
Now open a new terminal and you should see a friendly new message!
Each file on a UNIX system belongs to a user and a group.
users are accounts on the system, like the one you log in with. groups are collections of users.
To see what groups you belong to, just type
groups
:
~ $ groups
substack cdrom floppy audio dip video plugdev
To inspect the permissions on a file, use ls -l
:
~/doc $ ls -l b.txt
-rw-r--r-- 1 substack whatever 14 Dec 28 00:29 b.txt
Here we can see that the file b.txt
is owned by
the user substack
and the group whatever
.
There's also this part on the left:
-rw-r--r--
This string describes the permissions of the file.
The first character is reserved for some fancy uses, but after that there are 3 groups of 3 characters:
rwxrwxrwx
Each character describes a permission: (r)ead,
(w)rite, and e(x)ecute. A -
in place of one of
those letters means the permission is not
available.
If the e(x)ecute bit is enabled on a file for a user, it means the user can execute the file.
If the e(x)ecute bit is enabled on a directory for a user, it means the user can list the files in that directory.
- The first
rwx
says what the owner can do. - The second
rwx
says what users in the group can do. - The third
rwx
says what everyone else can do.
These three categories are called user (u), group (g), and other (o).
To change the permissions on a file, first figure out which capabilities you want to grant or revoke (rwx) from which categories of users (ugo).
To allow the owner of a file to execute a script you can do:
~ $ chmod u+x script.sh
which is the same as:
~ $ chmod +x script.sh
because the u
is implied if not specified.
You can also revoke permissions with a -
. To
make it so that other users can't write to a
file:
~ $ chmod o-w wow.txt
You can grant and revoke permissions at the same time. Here we're adding read and execute permissions to the user while simultaneously revoking read and write from the group:
~ $ chmod u+rxg-rw status.sh
You can change the owner of a file with chown
and the group with chgrp
.
Bash is built to handle multiple programs running in parallel.
Type time cat
and then hit ctrl-c before one
second, as close as possible without going over:
$ time cat
^C
real 0m0.920s
user 0m0.004s
sys 0m0.000s
Terminate a process in the foreground.
Put a process in the background.
Move a process from the background to the foreground by its JOB.
~ $ cat
^Z
[1]+ Stopped cat
~ $ echo wow
wow
~ $ fg %1
cat
cool
cool
When you background a process with ctrl-z, the
shell prints a message with [N]
. N
is the job
id. Use %N
to refer to a particular job or:
%%
- the most recent job
Another way to background a process is to use &
:
$ ~ node &
[1] 29877
The job id of node
is 1 and the process id is
29877. Job ids are local to a shell session, but
process ids are global across the entire system.
~ $ perl &
[1] 29870
~ $ pgrep perl
29870
~ $ kill %1
[1]+ Terminated perl
Search for a process by its name.
Kill a process by its process or job id.
You can use screen to run command-line programs and keep them running, even when you go away.
$ sudo apt-get install screen
$ screen -S website
$ screen -list
$ screen -x website
From inside of a screen, press CTRL+A then d
.
CTRL+A c
CTRL+A n
CTRL+A p
Just type exit
to close a window.
Install irssi:
$ sudo apt-get install irssi
Then create a screen for irc:
$ screen -S irc
Then in a screen, you can run irssi
to use irc from the
command line.
/nick robowizard
- set your nickname on the server/connect irc.freenode.net
- connect to irc.freenode.net/join #cyberwizard
- join the channel called cyberwizard- ESC+N or
/win N
- to jump to the window at number N
Once you're in a channel, type text like usual.
CTRL+A d
to detach and screen -x irc
to resume.
Make a web server.js:
var http = require('http');
var server = http.createServer(function (req, res) {
res.end("YOU'RE A WIZARD.\n");
});
server.listen(8000);
now run your server with node from inside a screen:
$ node server.js
then detach the screen with CTRL+A d.