theme | footer | marp |
---|---|---|
sam-theme |
Sam Bail @spbail - Intro to terminal workshop |
true |
https://github.com/spbail/terminal-workshop
- Hello! I'm Sam!
- I'm a data... person in New York City, and I run our Partnerships team at Superconductive
- We are the team behind Great Expectations, an awesome open source tool for data quality!
- Plan for today:
- Some background and terminology
- Basic navigation, file manipulation, searching
- Environment variables and shell profile
- Shell scripting
- I will mostly be showing slides and demo-ing in the terminal
- There will be stops after each section for questions
- We will have time for an FAQ at the end
- The DIY blocks are mini-exercises you can try out after the workshop
<style scoped> h1 {margin-top: 120px;} p {font-size: 0.8em; margin-top:2em;} </style>
- Shell: user interface (command-line or graphical)
- Usually shell = command-line user interface
- The Wikipedia pages on "Unix shell" and "Bash (Unix shell)" are a good read if you're interested in some history!
- Bash: a type of shell (“Bourne-Again SHell”)*
- There are others: zsh, ksh…
- macOS switched from bash to zsh in 10.15
- The basics are all the same :)
- Terminal: the program than runs a shell
- It’s often faster or more flexible
- Bulk operations on files
- Searching for files/text in files
- ...
- Sometimes you have to
- Connecting to a server via ssh
- Setting aliases or environment variables
- ...
- MacOS
- The built-in Terminal app works well!
- iTerm is a nice terminal with a few more customizable features
- Windows
- The Windows command line is very different from the Unix shells
- Git Bash is a bash-like wrapper around the command line, it comes with the git for Windows install
- There is a feature called "Windows subsystem for Linux" that gives you Unix features like a shell - I haven't tested this yet but it might be an option!
<style scoped> h1 {margin-top: 120px;} p {font-size: 0.8em; margin-top:2em;} </style>
- Some basics to navigate the file system:
pwd
: path of current working directory (usually your terminal will open a shell in your home directory, but you can change that in settings)ls
: list files in the directoryls -l
: add a “long format” flagls -la
: add long format + “all” flag
- How do we know what flags are available?
man ls
: man(ual) pages<space bar>
: navigate downq
: get out ofman
(and lots of other shell programs)!
- DIY: check man and try out different flags for
ls
clear
or<CTRL+L>
: refresh your terminal window<Up arrow>
: cycle through previous commands<Tab>
: bash will tab-complete file/dir paths<CTRL+c>
: exit pretty much any process<CTRL+a>/<CTRL+e>
: go to start/end of line<CTRL+w>
: delete word before the cursor<CTRL+r>
: incremental reverse search through previous commands, keep hitting<CTRL+r>
to cycle- DIY: use
<CTRL+r>
to find and run your firstpwd
command
cd <directory>
: go to- Use pwd, tab-complete and ls for orientation!
- Example:
- Use
pwd
to see where you are, thenls
to list contents of the directory - Change to the "code" subdir with
cd code
and list contents withls
- Use
- Some useful aliases for directories:
~
: alias for your home directory (/Users/).
: alias for the current directory..
: alias for the parent directory
- DIY: Try out navigating your file system using names and aliases
<style scoped> h1 {margin-top: 120px;} p {font-size: 0.8em; margin-top:2em;} </style>
mkdir <directory>
: make a directorytouch <filename>
: create an empty file calledopen (filename)
: open file in default text editor`- Example:
mkdir some_dir
andcd some_dir
touch hello.txt
andls
to see that file was createdopen hello.txt
to open the file in your system's default editor
- DIY: Try out this workflow!
cp <file1> <file2>
: copy file1 to file2cp hello.txt hello2.txt
ls
mv <file1> <file2>
: rename file1 to file2mv hello2.txt hello3.txt
ls
- we now have only hello.txt and hello3.txt
rm <file>
: remove file (irreversibly!)- Use wildcard
*
in file names for any operationls hello*
will show all files starting with "hello"
- I'm using a file (permits.csv) from NYC OpenData as an example
cat
: print content of filehead
: cat, but only show the top n rows of a filetail
: like head, but shows bottom n rows- Example:
cat permits.csv
head permits.csv
andhead -n 2 permits.csv
tail permits.csv
andtail -n 2 permits.csv
less
: interactive text reader (a little fancier thancat
)less permits.csv
- Navigate with arrow keys, skip whole pages with
<space bar>
- Lots of other functionality in
less
, but let's exit withq
- (What does this remind you of?)
<style scoped> h1 {margin-top: 120px;} p {font-size: 0.8em; margin-top:2em;} </style>
- Option 1:
less
has a built-in search less permits.csv
/
(this gets you the search prompt)- type for example
film
and hit enter - This will say “Pattern not found” because the search is case sensitive
- Case insensitive search:
- Type
-I
to make the search case insensitive - Try searching again!
- Type
p
andn
: jump to previous/next occurrence of the search word
- Option 2: use
grep
grep <search word> <file>
- Example:
grep film permits.csv
- No results! grep is case sensitive, too
- Try
grep -i film permits.csv
- Example:
- grep returns all lines containing the search word
- Works best with line-based files, e.g. CSV
- DIY: grep for the word “theater”
- This is not file related, but I use it a lot in the way shown here!
|
: the pipe operator chains any two commands and "pipes" the output of command a into command b<command a> | <command b>
- Let's try this:
wc -l <file>
: counts lines in a file, e.g.wc -l permits.csv
grep -i film permits.csv | wc -l
pipes the result of thegrep
towc
- Pipes can be chained, e.g.
<command a> | <command b> | <command c>
- Output of a = input to b
- Output of b = input to c
- Go to the directory with permits.csv
- Look at the file using
head
,tail
, andless
- Get some counts using
grep
andwc
:- How many lines are in the file?
- How many lines contain the word “Television”?
- How many lines contain the word “Television” and your own ZIP code? (Hint: remember you can chain pipes!)
<style scoped> h1 {margin-top: 120px;} p {font-size: 0.8em; margin-top:2em;} </style>
- The
find
command lets you find files based on search criteria find <directory> -name "<search word>"
- I mostly use it to find filenames, e.g.
find . -name "per*"
: find file starting with "per"find . -iname "PER*"
: case insensitive versionfind . -name "*.csv"
: find file type with extension ".csv"
- You can also specify a directory to search in:
find ~/code -name "*.csv"
find
is recursive by default (yay)- I sometimes do stuff like
find ~/code -name "npi*.csv" | grep wc -l
<style scoped> h1 {margin-top: 120px;} p {font-size: 0.8em; margin-top:2em;} </style>
- Environment variables are system-wide global variables that your shell knows about
env
: show all environment variables- You can access any variable using the $ sign
echo $USER <your username>
echo $HOME <your home directory>
- We also just learned the
echo
command that prints text to the terminalecho "hello"
: this just prints the "hello""echo "hello $USER"
: variables are substituted in anecho
statement
export <varname>=<value>
sets an environment varexport myvar=42
orexport myvar="some text"
echo $myvar
- Setting environment vars is often done for software to know where to find relevant libraries, e.g.
$PYTHONPATH
- Two important things to note:
- Spaces and quote types matter in bash
- Any environment variable you set in a shell will only be known to this instance of the shell, e.g.
echo $myvar
in a new terminal tab or window won't show anything
- Every terminal window/tab only knows about its own environment variables
- Variables that are needed everywhere need to be exported at startup
- Your terminal reads a “profile” file at startup to "source" environment variables, functions, aliases, etc.
- bash: ~/.bash_profile, ~/.profile, ~/.bashrc - feel free to read up on the differences!
- zsh: ~/.zshrc
- Let’s export a new environment variable via the shell profile
open ~/.zshrc
- Add this line:
export anothervar=”hello”
- Save the file
echo $anothervar
- My open shell doesn’t know about changes to .zshrc automatically, I need to:
- Either: open a new terminal which will source the profile at startup
- Or: run
source ~/.zshrc
<style scoped> h1 {margin-top: 120px;} p {font-size: 0.8em; margin-top:2em;} </style>
- Instead of typing commands, you can also add them to a file and execute the file
- My script "samscript.sh" does a simple
echo
- There are several options to execute a script:
./samscript.sh
bash samscript.sh
sh samscript.sh
- DIY: create a new file myscript.sh and add a line to echo “Hello $USER!”, save the file, and execute
- You’ll get a “permission denied” error
- Files in your file system have permissions for who can do what
ls -l
shows-rw-r--r--
for samscript.sh
- The permissions are as follows:
- The first bit is either
d
(directory) or-
(file) - Then we have 3-letter-blocks each for owner/user, group, other
r
: read,w
: write,x
: execute,-
: permission not set
- The first bit is either
- The
chmod
command changes the “mode” (permissions) of a filechmod u+x samscript.sh
to allow the user to execute the scriptls -l samscript.sh
to show the updated permissions
- We can now run the script with
./samscript.sh
!
- Create a new bash script
- Add at least 2 commands you’ve learned
- Save the file
- Set the right permissions
- Execute the script
- We’ve covered:
- Directory navigation and file manipulation
- Searching for text and finding files
- Environment variables and your shell profile
- Other important or fun shell things to look up (e.g. using
man
):- The
sudo
command - Setting an alias (shortcut) for shell commands
- Using vim as text editor,
csvkit
, etc. - Other ways to exit and kill processes (CTRL+z, CTRL+d…)
- Utilities like
cal
,date
, disk space checking,cowsay
...
- The
<style scoped> h1 {margin-top: 120px;} p {font-size: 0.8em; margin-top:2em;} </style>