Definitions – Choosing a Shell – Shell Features



Definitions – Choosing a Shell – Shell Features

0 0


talk-effective-shell

Effective Shell talk for Northeastern

On Github pbrisbin / talk-effective-shell

Effective Shell

% whoami
Pat Brisbin - Developer at thoughtbot
http://pbrisbin.com
@patbrisbin
me@pbrisbin.com
% head -n 1 /var/log/pacman.log | sed 's/^\[\(.*\)\].*/\1/'
2007-04-25 00:04

Definitions

Unix

Category of close-source operating systems

"The Unix Philosophy"

Re-implemented as open-source many times

  • BSD ⇒ OSX
  • GNU ⇒ GNU/Linux

Command

Anything that can be "invoked"

  • Compiled binary
  • Interpreted script
  • Shell built-in, alias, or function

Shell

A command for running other commands

Choosing a Shell

POSIX sh

Idealized shell with all (and only) the functionality outlined in the specification

Does not exist

SH

BSD

Very close to POSIX

Bash

OSX, Arch Linux

Arrays, regular expressions

When invoked as sh, tries to be POSIX

Personal favorite for non-interactive use

Dash

Debian (Ubuntu et al)

Similar to Bash with subtle differences

Also tries to be POSIX if invoked as sh

ZSH

Newest / widely adopted shell

Suffix and global aliases, better tab-completion, fancy globs

Personal favorite for interactive use

Installing ZSH

Google: switch to zsh on OSX

Do not install Oh-my-zsh (yet)

Consider grml-zsh-config

Shell Features

Aliases

% alias v='vim'
% v --version
# shows vim --version...

ZSH Aliases

% alias -s txt="less"
% ./something.txt
# opens the file in less...
% alias -g L='| less'
% grep pattern file.text L
# same as grep ... | less

Globs

% ls *.mp4
foo.mp4 bar.mp4
% for file in *.mp4; do
>   echo "A file! $file"
> done
A file! foo.mp4
A file! bar.mp4

ZSH Globs

% ls *(.)  # * but files only
foo.txt bar.txt
% ls *(/)  # * but directories only
baz/ bat/

And about a 1,000 more...

IO Redirection

% command 2>/dev/null
% command &>/dev/null
% command >/dev/null 2>&1
% echo "I'll go to stdout" >&2
% cat file.txt | grep 'some-pattern'
% grep 'some-pattern' < file.txt
% grep 'some-pattern' file.txt

Expansions

% for x in {1..3}; do
>   echo "$x"
> done
1
2
3
% ls
file
% cp file{,.bak}
% ls
file file.bak
% mkdir -p test/{models,views}/{lib,ext}
% tree test
test
├── models
│   ├── ext
│   └── lib
└── views
    ├── ext
    └── lib

6 directories, 0 files

ZSH Completion

Other Tools

Cat

% cat file.txt
one line
two line
three line
four
% cat other-file.txt
five and six
seven
% cat file.txt other-file.txt
one line
two line
three line
four
five and six
seven

Grep

% grep line file.txt
one line
two line
three line
% cat file.txt other-file.txt | grep five
five and six
% grep -q line file.txt; echo $?
0
% grep -q "something else" file.txt; echo $?
1

Cut

% cut -d ' ' -f 2 file.txt
line
line
line
% cut -d e -f 1 file.txt
on
two lin
three lin
four

Sed

% sed 's/line/word/' file.txt
one word
two word
three word
four
% sed '/\(.*\) \(.*\)/!d; s//\1-"\2"/'
one-"line"
two-"line"
three-"line"

Building a Command Line

Pipeline

% grep -F 'error' log.txt | cut -d ' ' -f 3 | sort | uniq -c | sort -rn
    12 2013-03-05
     7 2013-03-08
     6 2013-03-04
     4 2013-03-06
     3 2013-03-02
     1 2013-03-09

Build these up incrementally

Control Flow

% grep -Fq ':./bin:' <<<":$PATH:" || PATH="./bin:$PATH"

Multi-line

% printf "%s\n" "foo" "bar" |\
>   grep "o" | sed 's/f/m/'
moo

Multi-line (implicit)

% for file in *; do
>   # ...
> done
% if thing; then
>   # ...
> fi

Functions

% fix_file() {
>   local file="$1" fixed_file
>
>   # lower case letters, remove spaces etc
>   fixed_file="$( ... )"
>
>   echo "$fixed_file"
> }
% for file in *; do
>   fixed="$(fix_file "$file")
>
>   mv "$file" "$fixed"
> done

Example 1

Cleaning up Files

% ls -1
hot.rod.mp4
The Big Lebowski.m4v
in-Bruges.iso
bRick.mp4
% for file in *; do
>   echo "$file"
> done
hot.rod.mp4
The Big Lebowski.m4v
in-Bruges.iso
bRick.mp4
% var="hot.rod.mp4"
% echo "${var%.*}"
hot.rod
% echo "%{var##*.}"
mp4
% for file in *; do
>   title="${file%.*}"
>   ext="${file##*.}"
>   echo "$title ($ext)"
> done
hot.rod (mp4)
The Big Lebowski (m4v)
in-Bruges (iso)
bRick (mp4)
% echo "A-really bad.title" | sed 's/[ -.]\+/_/g; s/.*/\L&/'
"a_really_bad_title"
% for file in *; do
>   fixed="$(echo "${file%.*}" | sed 's/[ -.]\+/_/g; s/.*/\L&/')"
>   ext="${file##*.}"
>   echo "$fixed ($ext)"
> done
hot_rod (mp4)
the_big_lebowski (m4v)
in_bruges (iso)
brick (mp4)
% for file in *; do
>   fixed="$(echo "${file%.*}" | sed 's/[ -.]\+/_/g; s/.*/\L&/')"
>   ext="${file##*.}"
>   mv -v "$file" "$fixed.$ext"
> done
’hot.rod.mp4’ -> ’hot_rod.mp4’
’The Big Lebowski.m4v’ -> ’the_big_lebowski.m4v’
’in-Bruges.iso’ -> ’in_bruges.iso’
’bRick.mp4’ -> ’brick.mp4’

Example 2

Building a Talk

Manual

  • Go to GitHub
  • Click on Releases
  • Click on version
  • Find archive in Downloads
  • Double click in File manager
  • Find folder in Downloads
  • Move to real location
  • Cleanup download artifacts
  • Add/edit content
% curl -s -L "https://github.com/hakimel/reveal.js/archive/2.6.1.tar.gz" | tar xvf -
% mv reveal.js-2.6.1 my_talk
% cd my_talk
% vim index.html
#!/bin/sh

talks="$HOME/Code/talks"
reveal_version='2.6.1'
reveal_src_url="https://github.com/hakimel/reveal.js/archive/${reveal_version}.tar.gz"

title="$*"
directory="$talks/$(printf "$title" | sed 's/.*/\L&/; s/ \+/_/g')"

curl -L -# "$reveal_src_url" | tar fxz -
mv "reveal.js-$reveal_version" "$directory"

cat > "$directory/index.html" << EOF
<!doctype html>
<html lang="en">
  <!-- ... -->
</html>
EOF
% ./new-talk Effective Shell
% vim effective_shell/slides/title.md

Thanks