Lab 05: Terminal Tidbits

The Joy and Ease of GUI

Your operating system likely provides a convenient, mouse-based and graphical means to interact with your file system.

  • Moving files? Click and drag!
  • Copying files? Right-click. Copy. Paste!
  • Removing files? Right-click. Delete!

I was so blinded by the first thing they showed me, which was the graphical user interface. I thought it was the best thing I’d ever seen in my life. – Steve Jobs on one of the early GUI systems

The Terminal

Today, we’ll introduce how to do the same operations and more via the terminal.

For now, think of the terminal simply as a text-based way for you to invoke programs. These programs each,

  • have a name (e.g., cd),
  • will receive arguments from you,
  • and will take actions on your computer on your behalf. This often includes communicating directly with the kernel.

Programs == Commands

One note on terminology:

The programs we’ll be using are often referred to as commands.1

An Introductory Example

Here we invoke a program, cp, which copies note.txt into the directory notes/, but doesn’t override the file if it already exists there.

cp --no-clobber note.txt notes/

At a high level, we invoke a program (issue a command) with,

<program> <arguments ... >

What the Program Sees

Programs are unlike functions in R. They do not receive typed objects as arguments, but merely a list of strings. Here’s an example.

// hello.cpp
#include <iostream>

auto main(int argc, char** argv) -> int {
  if (argc == 2) {
    std::cout << "Hello, " << argv[1] << '\n';
  }
}

Compiling the program:

g++ -std=c++20 -o hello hello.cpp

Running it with the argument, Jakob.

./hello Jakob
Hello, Jakob

What the Program Sees

To better demonstrate, here’s a program that simply prints all its arguments.

// print_all.cpp
#include <iostream>

auto main(int argc, char** argv) -> int {
  for (int i = 0; i < argc; ++i) {
    std::cout << "Argument #" << i << ": " << argv[i] << '\n';
   }
}
./print_all
Argument #0 : /path/to/.../stat133/lab05/print_all
./print_all a 15
Argument #0: /path/to/.../stat133/lab05/print_all
Argument #1: a
Argument #2: 15
./print_all a b c d e f
Argument #0: /path/to/.../stat133/lab05/print_all
Argument #1: a
Argument #2: b
Argument #3: c
Argument #4: d
Argument #5: e
Argument #6: f

Argument Rules

As you can see, the program has free rein to do whatever it likes with the strings (arguments) you pass.

Thankfully there are a set of conventions.

Arguments: Key-Value Options

Program options are often akin to named arguments in R. That is, they are key-value pairs.

Suppose we have a function sum(first, second) in R. We may call it as,

sum(first = 10, second = 30)

Programs typically have the key set with

  • --<key name> or,
  • -<key shorthand>.

The value follows immediately after the key name, e.g.,

sum --first 10 --second 30
sum -f 10 -s 30  # shorthand -- note that it uses 1 dash

Arguments: Key-Value Options

Or sometimes you will need to set it with an = right after the key name, i.e.,

sum --first=10 --second=30 # note the lack of spaces

Arguments: Flag Options

Some options are not key-value pairs. Instead, their presence alone informs the program to do something. These are called flags.

You can think of it like setting an argument typically defaulted to FALSE to TRUE in R.

read.table("some-file", flush=TRUE)

Or for an equivalent program,

readtable some-file --flush
readtable some-file -f # potential shorthand

Arguments: Those Not Optional

Notice that we called the previous arguments options. They are called as such as they are optional.

Some arguments are required. These are typically provided based on position.

A more accurate summary:

<program> <options...> <required arguments...>

Now reconsider our first example:

cp --no-clobber note.txt notes/

Here, --no-clobber is the option and the next two are the required arguments. They represent the source and destination, respectively.

Program Arguments: Getting Help

Enter man <program> to pull up the manual for a particular command.

Here’s an example from the command ls:

-a, --all
     do not ignore entries starting with .

-A, --almost-all
    do not list implied . and ..

--author
    with -l, print the author of each file

-b, --escape
    print C-style escapes for nongraphic characters

--block-size=SIZE
    with  -l,  scale  sizes  by  SIZE  when  printing  them;   e.g.,
    '--block-size=M'; see SIZE format below

Notice that many arguments have both verbose and shorthand versions (e.g., -A vs. --almost-all).

Program Arguments: Getting Help

Many programs also have a --help option to output a usage guide instead of running the program as usual.

ls --help

If needed, most programs also allow you to check the version with --version.

ls --version

Conventions and Conventions Only!

Remember, these are just conventions, not rules.

Always check the documentation.

Where am I, anyway?

Think of your terminal as existing inside a directory (folder). All commands issued will be relative to this position.

We call this the,

current working directory.

Use the command pwd to print the current working directory.

Importantly, we use,

  • . (one period) to refer to the current working directory (often implicit).
  • .. (two periods) to refer to the parent directory.

Really, where am I?

Consider the following directory structure:

- stuff
  todo.txt
  - books
    - moby_dick.pdf
    - obedience_to_authority.pdf
    - little_women.pdf
    - school
      - stat133.pdf
  - code
    - hack_nsa.cpp
    - ai_friend.py

Really, where am I?

Consider the following directory structure:

- stuff
  todo.txt
  - books <- suppose this is the current working directory
    - moby_dick.pdf
    - obedience_to_authority.pdf
    - little_women.pdf
    - school
      - stat133.pdf
  - code
    - hack_nsa.cpp
    - ai_friend.py

Which path should I provide to refer to hack_nsa.cpp?

../code/hack_nsa.cpp

Really, where am I?

Consider the following directory structure:

- stuff
  todo.txt
  - books 
    - moby_dick.pdf
    - obedience_to_authority.pdf
    - little_women.pdf
    - school <- suppose this is the current working directory
      - stat133.pdf
  - code
    - hack_nsa.cpp
    - ai_friend.py

Which path should I provide to refer to todo.txt?

../../todo.txt

Is ../../../stuff/code/../todo.txt equivalent?

Really, where am I?

Consider the following directory structure:

- stuff <- suppose this is the current working directory
  todo.txt
  - books 
    - moby_dick.pdf
    - obedience_to_authority.pdf
    - little_women.pdf
    - school 
      - stat133.pdf
  - code
    - hack_nsa.cpp
    - ai_friend.py

Which path should I provide to refer to stat133.pdf?

./books/school/stat133.pdf

Is books/school/stat133.pdf equivalent?

Changing Directories

It would be inconvenient if we were stuck in one directory. We can change our current working directory with the commmand cd.

- stuff <- suppose this is the current working directory
  todo.txt
  - books 
    - moby_dick.pdf
    - obedience_to_authority.pdf
    - little_women.pdf
    - school 
      - stat133.pdf
  - code
    - hack_nsa.cpp
    - ai_friend.py

What’s our working directory after running the following line?

cd ../stuff/./code/../books/school/../../.,

stuff

Synopsis of Helpful Commands

Below you’ll find a list of helpful commands you should be aware of (you can scroll).

  • mkdir <options> <directory>: Make a directory <directory>.
  • rm <options> <file or directory>: Remove files or directories. Use the flag -r (recursive) to remove directories – be careful!
  • ls <options> <file or directory>: List information about files or directories. If not specified, the current directory is used.
  • cp <options> <source> <destination>: Copy file(s) <source> to <destination>. Destination can be a file name or directory.
  • mv <options> <source> <destination>: Move file(s) <source> to <destination> (or equivalently, rename the file from <source>
  • touch <file>: Create an empty file named <file>.
  • cat <file>: Print the contents of <file> to the terminal.
  • head <file>: Print the first part of <file> to the terminal.
  • tail <file>: Print the last part of <file> to the terminal.
  • cd <directory>: Change the current working directory to <directory>.
  • pwd: Print the current working directory to the terminal. to <destination>.

Some Tips

My primary tip is this: don’t add spaces to file or directory names!

If you do this, you will be required to add quotes to refer to the name. Compare:

cat 'Stat 133'/'Lab 3'/'My Awesome.Rmd'
cat stat133/lab3/my-awesome.Rmd

I also prefer prepending 0s to ordered names to ensure they are ordered when listed.

lab01.Rmd
lab02.Rmd
...
lab10.Rmd
lab11.Rmd
...