On Github briandailey / talk-cli-intro
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.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.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
An enigma...
Wrapped in a mystery.
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.
"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...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."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.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!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."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 |
4 uniq -c | 5 sort -rn | 6 sed ${1}q
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
$ ls Gr[tab] $ ls Gruntfile.js $ ls i[tab][tab] img/ index.html $ git commit [tab] $ git commit index.htmlAuto 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.
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
!! 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.
# 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.txtFor 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.
# sort lines and print to stdout $ sort < myfile.txt # same, but let's print to a file. $ sort < myfile.txt > sorted_myfile.txtHere we are redirecting a file to stdin. The second example directs the stdout of that filter to a file.
# Grab first line, replace tabs with line # return, and paginate with numbers. head -1 FLAT_RCL.txt | tr "\t" "\n" | less -N
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."
"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
If you are repeating yourself...
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.
colordiff --side-by-side \ <(httphead google.com | cut -d ":" -f 1 | sort) \ <(httphead github.com | cut -d ":" -f 1 | sort) | \ grep -v "[<>|]"
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...
(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.dailytechnology.net/talk-cli-intro
Thanks to Jason Orendorff, Jason Myers, and others for reviewing.