man
Will open the manual page for a command. For example:man cat
apropos
orman -k
will find a man page for a specific topic. For example,apropos copy
- The up and down arrows can be used to cycle through recent commands.
- The tab key will complete a command
history
will show the most recent commands- Ctrl-r will search through the history
- The current directory can be referred to as
.
and the parent directory can be referred to as..
- The home directory can be referred to as
~
- The last command can be referred to with
!!
, which is especially useful if you forget to addsudo
in front of a command that needs privilege elevation.
clear
is used to clear the terminal screenreset
will reinitialize the terminal
pwd
displays the full path for the current directorycd
change directorycd some/file/path
will change the working directory to the specified directory.cd
with no arguments, as well ascd ~
will change to your home directorycd /
change to the root directorycd ..
change to the parent directorycd -
change to the previous working directory
ls
lists files-a
include hidden files (those that start with a.
)-l
list in a long format-t
sort by time last modified, newest first-r
reverse sorting-R
recursively include the contents of directories-h
human-readable size units when used with-l
-U
don't sort (useful for large directories)
touch
create a new empty file if the file has not been created, update the timestamp if it has been creatednano
,vi
open a file in a text editormkdir
create a directory-p
create parent directories if needed
rm
remove a file or directory-rf
is used to delete directories and their contents
rmdir
remove a directory if it is empty
less
is a nice way to view long filesbc
is a calculator languagedate
shows the datecal
shows a calendar
We have two main wildcard characters that we can use. ?
is a one character,
and *
can match any number of characters. It's worth noting that *
excludes
files and directories beginning with a .
Normally, every program has three streams; input, output, and error.
Standard in, sometimes shortened to stdin, is usually the keyboard, but
sometimes it can be a file. To see this, if you just type cat
it will simply
return any input that you give it. In this mode, standard in is the keyboard. If
you give cat a filename, like cat /etc/passwd
or cat < /etc/passwd
the file
specified is the standard in. Note that angle brackets < >
can be used to
redirect input and output. Also note that cat is short for "concatenate",
because you can specify multiple files and it will concatenate them.
Standard out, shortened to stdout, is sometimes the terminal window, but it
can also be a file. If you type echo "test"
, the output will be sent to the
terminal window. echo "test" > test.txt
will output to the specified file. If
you'd like to append a file rather than overwriting it, try echo "test" >> test.txt"
The output of a file could be valid output or it could be an error message.
Standard error, shortened to stderr, is where these error messages are sent.
find / -iname '*stuff*'
will result in many error messages unless we redirect
standard error. That can be done with find / -iname '*stuff*' 2> /dev/null
Pipes allow you to use the output of one program as the input for another. This allows for the stringing together of many commands.
The pipe is the very thing that shaped the UNIX philosophy, which is best summarized as
- Write programs that do one thing and do it well
- Write programs so that they can work together
- Write programs that handle text streams, because they are a universal interface
The best illustration of the UNIX philosophy is Jon Bentley's challenge. He challenged Donald Knuth and Doug McIlroy to write a program that reads a file of text, determine the n most frequently used words, and print out a sorted list of those words along with their frequencies.
Download the complete works of Shakespeare to demonstrate this.
curl -o shakespeare.txt https://www.gutenberg.org/files/100/100-0.txt
Don Knuth's solution was over 10 pages of Pascal, but McIlroy's solution can be written as one simple line.
cat shakespeare.txt | tr -cs A-Za-z '\n' | tr A-Z a-z | sort | uniq -c | sort -rn | sed ${1}q
This can also be extended to the most occurences of multiple words in sequence.
Bigrams
cat shakespeare.txt | tr -cs A-Za-z '\n' | tr A-Z a-z | awk -- 'prev!="" { print prev,$0; } { prev=$0; }' | sort | uniq -c | sort -rn | sed 1q
Trigrams
cat shakespeare.txt | tr -cs A-Za-z '\n' | tr A-Z a-z | awk -- 'first!=""&&second!="" { print first,second,$0; } { first=second; second=$0; }' | sort | uniq -c | sort -rn | sed 1q
If we'd like to write longer programs, it's useful to make scripts so we can take advantage of conditional statements, loops, and arguments.
A shell script should be started with a #!
and then the path to the scripting
interpreter's binary file. If there's no "shebang line" the sh interpreter will
be used. Also be sure to set the execute bit on your scripts so
they are executable. chmod +x script.sh
Just like any programming language, you can use variables. There aren't any variable types, and there's no need to declare a variable before you assign it.
#!/bin/bash
STR="Hello, world!"
echo "$STR"
Arguments in bash are referred to as $1
as the first argument, $2
as the
second argument, and so on. $*
and $@
both refer to all elements, but when
double quoted, $*
places all arguments in a single string, whereas $@
gives
each element its own string.. $#
is the number of arguments.
#!/bin/bash
echo $(($1 * 2))
If statements are done in the format
if condition; then
# do something
elif condition; then
# do something else
else
# do another thing
done
The elif
and else
are not required, but done
is necessary to end
conditional statements. An example of this would be
#!/bin/bash
if (( $1 % 2 == 0 )); then
echo "even"
elif (( $1 % 3 == 0 )); then
echo "divisible by 3 but not even"
else echo "neither divisible by three nor two"
fi
There are two options for loops; for and while. The syntax of for loops is
for i in some set of things; do
# do something
done
The syntax of while loops is
while condition; do
# do something
done
#!/bin/bash
parse_args() {
while [ "$#" -gt 0 ]; do
case "$1" in
-o|--oof) print_oof=1; shift 1;;
-b|--bentley) bentley_challenge=1; bentley_file="$2"; shift 2;;
-t) print_if_true=1: shift 1;;
*) exit 1;;
esac
done
}
bentley() {
curl -o /tmp/shakespeare.txt "$1"
cat /tmp/shakespeare.txt | tr -cs A-Za-z '\n' | tr A-Z a-z | sort | uniq -c \
| sort -rn | sed 1q
}
main() {
print_oof=0
bentley_challenge=0
print_if_true=0
parse_args "$@"
if [ "$print_oof" -eq 1 ]; then
echo "oof"
fi
if [ "$bentley_challenge" -eq 1 ]; then
bentley "$bentley_file"
fi
if [ "$print_if_true" -eq 1 ]; then
echo "Big if true!"
fi
}
main "$@"