Command Line Kung Fu – The shell, and why you should care



Command Line Kung Fu – The shell, and why you should care

1 0


talk-cli-intro

Intro to the CLI Kung Foo talk.

On Github briandailey / talk-cli-intro

Command Line Kung Fu

The shell, and why you should care

Brian Dailey (@byeliad)

Hi! My name is Brian Dailey. This is a talk about the Unix shell environment. What it is, why you should know it, and some helpful tips and tricks to get you going. CLI is seeing more use compared to 5 years prior, especially BSD-based Mac OS X. Hopefully even if you're wizened, you'll learn some new tricks. My background started in MS-DOS 5.0 in 1995. Didn't like Win95. Introduced to Redhat 7.2 in 2001, Knoppix, DSL. 2006 and on, Ubuntu. 2012, Mac reluctantly embraced.

The Shell

Evolved from a text only environment.

* If you don't know what the shell is at all, it's * a way to interface with computers that involves only a keyboard. * existed prior to the WIMP interface we know today. * evolved from typewriters connected to line printers.
$ input output $ input output
When you start a shell, usually you'll see a simple text prompt and little else. It may seem intimidating, but fundamentally it's just a machine that accepts input and accepts output. It may do it a little differently than you're used to.

You ▲ ▼ Shell ▲ ▼ Computer

You can think of the shell as a layer that sits between you and the computer

It's A Little Terse

1  tr -cs A-Za-z '\n' |
2  tr A-Z a-z |
3  sort |
4  uniq -c |
5  sort -rn |
6  sed ${1}q

Some might say "Cryptic"

To the unitiated, it might seem..

An enigma...

Wrapped in a mystery.

Swallowed by a Chupacabra

Eaten by a Deep Crow

Consumed by Cthulhu

However, once you spend some time with it, you'll see it's not really all that scary.

You need not look like a wizard to be a CLUI wizard.

This is Ken Thompson and Dennis Ritchie, two developers of Unix and evangelists of the Unix philosophy.

So let's talk about what makes it worth your time.

Unix Philosophy

Cobbed together over time by the core developers of the Unix operating system as well as those writing some of it's most commonly used tools.

"Although [this] philosophy can't be written down in a single sentence, at its heart is the idea that the power of a system comes more from the relationships among programs than from the programs themselves. Many UNIX programs do quite trivial things in isolation, but, combined with other programs, become general and useful tools." — The Unix Programming Environment

In their preface to the 1984 book, The UNIX Programming Environment, Brian Kernighan and Rob Pike, both from Bell Labs, give a brief description of the Unix design and the Unix philosophy... Now he said we can't summarize it in one sentence, but the key takeaway for this talk is...

Relationships > Programs

"...simplicity of both the interface and the implementation are more important than any other attributes of the system—including correctness, consistency, and completeness." To sum it up even further...

Modularity

Components that can be arranged in many different ways.

4 Tenets

* This dapper lad is Doug McIlroy. He is the inventor of pipes, which we'll talk about shorlty. * Some say this guy can read data from /dev/null * In 1984, the Department of Justice broke up AT&T because they had a monopoly. On Doug McIlroy. * He wrote three guiding principles for the Unix philosophy.

1.

Make each program do one thing well. To do a new job, build afresh rather than complicate old programs by adding new features.

Modularity - composability - "components that can be selected and assembled in various combinations to satisfy specific user requirements."

2.

Expect the output of every program to become the input to another, as yet unknown, program. Don't clutter output with extraneous information. Avoid stringently columnar or binary input formats. Don't insist on interactive input.

Second, the ability to take the output of one and put it into another. Don't expect interactive input.

3.

Design and build software, even operating systems, to be tried early, ideally within weeks. Don't hesitate to throw away the clumsy parts and rebuild them.

Strike forward, but don't be afraid to abandon dead end trails!

4.

Use tools in preference to unskilled help to lighten a programming task, even if you have to detour to build the tools and expect to throw some of them out after you've finished using them.

Don't throw bodies at a problem that can be scripted.

So what does all of this mean for me?

Every *nix tool you learn multiplies the usefulness of the ones you already know.

I don't know about you, but... whoa.

"Read a file of text, determine the n most frequently used words, and print out a sorted list of those words along with their frequencies."

This was a 'problem' posed for Donald Knuth to answer to demonstrate literate programming. McIlroy was asked to write a literary style critique of it. Knuth's solution was presented lucidly, but it was 10+ pages long. He started out by appreciating the presentation and cleverness of the data structure, but then he dropped this...
1  tr -cs A-Za-z '\n' |
2  tr A-Z a-z |
3  sort |
4  uniq -c |
5  sort -rn |
6  sed ${1}q

"If you are not a UNIX adept, you may need a little explanation, but not much, to understand this pipeline of processes. The plan is easy:"

1  tr -cs A-Za-z '\n' |
2  tr A-Z a-z |
3  sort |
  • Make one-word lines by transliterating the complement (-c) of the alphabet into newlines (note the quoted newline), and squeezing out (-s) multiple newlines.
  • Transliterate upper case to lower case.
  • Sort to bring identical words together.
4  uniq -c |
5  sort -rn |
6  sed ${1}q
  • Replace each run of duplicate words with a single representative and include a count (-c).
  • Sort in reverse (-r) numeric (-n) order.
  • Pass through a stream editor; quit (q) after printing the number of lines designated by the script’s first parameter (${1}).

More reasons...

  • You're probably already using it.
  • You'll be able to work from nearly any *nix based platform.
  • Huge set of tools already exists to make your life easier.

Reason's not to...

The learning curve might seem a little steep at first. It seems intimidating, but it isn't.

Advanced Beginner,

Competent,

Or Proficient?

A lot of us may edge into the advanced beginner or competent but the sweet spot is proficient. That's where I want to be. I'm too dumb to be an expert, but you can aim for that.

So where do I start?

  • Amazon EC2 instance w/ Ubuntu
  • Ubuntu Live CD
  • Mac OS X + homebrew
  • Cygwin (if you must)

Getting Around

One of the first frustrations I see with shell inductees is getting around without a mouse. Moving the cursor around is not intuitive.

Moving the cursor:

  Ctrl + a   Go to the beginning of the line (Home)
  Ctrl + e   Go to the End of the line (End)
  Ctrl + p   Previous command (Up arrow)
  Ctrl + n   Next command (Down arrow)
   Alt + b   Back (left) one word
   Alt + f   Forward (right) one word
  Ctrl + f   Forward one character
  Ctrl + b   Backward one character
  Ctrl + xx  Toggle between the start of line and current cursor position

Editing:

 Ctrl + L   Clear the Screen, similar to the clear command
 Ctrl + u   Cut/delete the line before the cursor position.
  Alt + Del Delete the Word before the cursor.
  Alt + d   Delete the Word after the cursor.
 Ctrl + d   Delete character under the cursor
 Ctrl + h   Delete character before the cursor (backspace)
 Ctrl + w   Cut the Word before the cursor to the clipboard.
 Ctrl + k   Cut the Line after the cursor to the clipboard.
  Alt + t   Swap current word with previous
 Ctrl + t   Swap the last two characters before the cursor (typo).
 Esc  + t   Swap the last two words before the cursor.
 ctrl + y   Paste the last thing to be cut (yank)
  Alt + r   Cancel the changes and put back the line as it was in the history (revert).
 ctrl + _   Undo
 

Shell it Live!

Hope I don't screw it up!

Where do all of these shortcuts come from?

GNU Readline Library

Comes in emacs and vim mode flavors. I didn't discover vim mode before it was too late. emacs is default. Congrats, you are now an emacs wizard! Better insure your wrists. Beauty is that these are consistently available in many places: MySQL, Postgres, Python REPL, Ruby REPL, even PHP Interactive Shell.

Things you also get...

Tab Completion

$ ls Gr[tab]
$ ls Gruntfile.js
$ ls i[tab][tab]
img/     index.html
$ git commit [tab]
$ git commit index.html
Auto completes files and directories, and even arguments to commands. Can be very clever if you install some addon packages that will auto complete hostnames, context-sensitive arguments, and more.

GNU History Library

  Ctrl + r   Search back through history
  Ctrl + s   Search forward through history
   Alt + .   Use the last word of the previous command
  Ctrl + g   Escape from history searching mode

On argument reuse...

!!      Rerun previous command.
!l      Rerun previous command starting with 'l'
!l:p    Print (don't execute) last command starting with 'l'
!$      Last argument in previous command.
!*      All arguments in previous command.

Redirecting

Source: Wikipedia The shell introduces the concept of streams. stdin, stdout, and stderr. Typically, your keyboard is stdin and your display will receive stdout and stderr. However, this isn't always the case.

stdout to file

# sort lines and write to a file
sort myfile.txt > sorted_myfile.txt
# same as above, but append to existing file.
$ sort myfile2.txt >> sorted_myfile.txt
For starters, you can redir to a file. In the first example, stdout is redirected to a file. In the second example, we're doing the same thing but it appends to an existing file instead of overwriting it.

file to stdin

# sort lines and print to stdout
$ sort < myfile.txt
# same, but let's print to a file.
$ sort < myfile.txt > sorted_myfile.txt
Here we are redirecting a file to stdin. The second example directs the stdout of that filter to a file.
You can also redirect from one program to another. This is where the real power of the Unix philosophy of composability kicks in. You can feed output from one program to another.

|

Filtering is indicated by the almighty pipe. All hail the pipe.
# Grab first line, replace tabs with line
# return, and paginate with numbers.
head -1 FLAT_RCL.txt | tr "\t" "\n" | less -N

Shell it Live!

We're going to show how each of these commands work.

Pipes: How do they work?

  • Each command spawns its own process.
  • First program starts to push to stdout until it hits a buffer limit (imposed by your shell of choice).
  • As soon as it hits the limit, the process is blocked.
  • First filter process starts reading stdin, and incrementally starts passing stdout to the next process.
  • Some filters must wait until the entire output is available (e.g., sort) before they can continue, which can buffer to disk.
  • Continues until the last process is reached.

Example from Peter Sobot

cat /usr/share/dict/words |     # Read in the system's dictionary.
grep purple |                   # Find words containing 'purple'
awk '{print length($1), $1}' |  # Count the letters in each word
sort -n |                       # Sort lines ("${length} ${word}")
tail -n 1 |                     # Take the last line of the input
cut -d " " -f 2 |               # Take the second part of each line
cowsay -f tux                   # Print resulting word

Print out longest word containing 'purple'

 _____________ 
< unimpurpled >
 ------------- 
   \
    \
        .--.
       |o_o |
       |:_/ |
      //   \ \
     (|     | )
    /'\_   _/`\
    \___)=(___/

"Thanks to the fact that the pipeline only stores what it can process in memory, this solution is very memory-efficient and lightweight. Processing a file of any size would not have changed the memory usage of this solution - the pipeline runs in effectively constant space."

This is pretty fast.

As I will demonstrate in a moment, this is pretty fast.

NHTSA's Office of Defects Investigation (ODI) - Recalls - Recalls Flat File

"Manufacturers who determine that a product or piece of original equipment either has a safety defect or is not in compliance with Federal safety standards are required to notify the National Highway Traffic Safety Administration (NHTSA) within 5 business days. "

Source: Data.gov

Shell it Live!

If you are repeating yourself...

alias

alias l='ls -lt'
$ l
-rw-r--r--  1 brian  staff  108847839 Mar 17 19:35 FLAT_RCL.csv
-rw-r--r--  1 brian  staff       2407 Mar 17 19:16 RCL.txt
-rwxr-xr-x@ 1 brian  staff  108847839 Mar 17 04:46 FLAT_RCL.txt

Arguments get tacked on.

$ l FLAT_RCL.csv
-rw-r--r--  1 brian  staff  108847839 Mar 17 19:35 FLAT_RCL.csv

But there are limits...

# this would be handy!
$ alias headers = 'head -1 | tr "\t" "\n" | less -N'
# but there's no convenient way to put the filename into the first filter.
$ unalias headers
$ function headers() { head -1 $1 | tr "\t" "\n" | less -N }
# now we're cookin' with fire!
headers FLAT_RCL.txt

Another example...

$ function httphead () {
            wget -O - -o /dev/null --save-headers $1 | \
            awk 'BEGIN{skip=0}{ if (($0)=="\r") {skip=1;}; \
            if (skip==0) print $0 }'
}
$ httphead www.github.com
HTTP/1.1 200 OK
Server: GitHub.com
Date: Tue, 18 Mar 2014 00:56:13 GMT
Content-Type: text/html; charset=utf-8
Status: 200 OK
Cache-Control: private, max-age=0, must-revalidate
Strict-Transport-Security: max-age=31536000
...snip...

Let's say we wanted to see what HTTP headers Google and Github have in common.

SHELL IT LIVE

colordiff --side-by-side \
    <(httphead google.com | cut -d ":" -f 1 | sort) \
    <(httphead github.com | cut -d ":" -f 1 | sort) | \
    grep -v "[<>|]"

xargs

Your poor man's map function.

# this will pass all files to tail -1 together
find . -name "*.csv" | xargs tail -1
# this will call tail -1 on each file individually
find . -name "*.csv" | xargs -I {} tail -1 {}

You could live in the shell if you wanted to...

vim

emacs

lynx

(For the masochistic.)

Wrap-up!

I hope that this talk has given you a tast of what's available out there, and you are motivated to read more.

Additional Resources

THE END

BY Brian Dailey / @byeliad

Questions?

dailytechnology.net/talk-cli-intro

Thanks to Jason Orendorff, Jason Myers, and others for reviewing.