Skip to content

Latest commit

 

History

History
706 lines (526 loc) · 28.7 KB

shell-workshop.md

File metadata and controls

706 lines (526 loc) · 28.7 KB
title subtitle author date lang description reference-location
Mastering the Unix Command Line
University of Stirling Society of Computing
Michael Connor Buchan <[email protected]>
November 2023
en-GB
block Licensed under [CC By SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/deed.en)

You can create long pipelines to achieve something more complex, like this example, which prints misspelled words in a text file:

mikey@mikeys-thinkpad:~$ echo "thiis is a testt text file with sume mispelings in it" > test.txt
mikey@mikeys-thinkpad:~$ cat test.txt 
thiis is a testt text file with sume mispelings in it
mikey@mikeys-thinkpad:~$ cat test.txt | tr -s '[:space:]' '\n' | sort | uniq | aspell list
mispelings
sume
testt
thiis

This is why 2>&1 to combine stdout and stderr is useful. If you'd like to pipe both into another command, you can do so. For example, to run a command and send all its output into nano, a simple text editor:

mikey@mikeys-thinkpad:~$ ls --help 2>&1 | nano +1 -
  • LS: Command to run
  • --help: flag for ls
  • 2>&1 pipe stderr (stream 2) into stdout (stream 1)
  • | Pipe stdout into the stdin of the next command
  • nano: A basic text editor
  • +1: Tells nano to put the cursor on the first line, instead of the last one
  • -: Explicitly tells nano to read from stdin, otherwise it would just open a blank file

Environment variables and the search path

Shell Variables

While the shell is very conducive to being used interactively, it is, at heart, still a fully Turing complete programming language and, as you might expect as a result, it has variables.

mikey@mikeys-thinkpad:~$ x=1
mikey@mikeys-thinkpad:~$ y=hello
mikey@mikeys-thinkpad:~$ z="string with spaces"
mikey@mikeys-thinkpad:~$ echo "x = $x, y = $y, z = $z"
x = 1, y = hello, z = string with spaces

All variables in the shell store text 1, after all text is the basic unit of data that the shell processes.


This can be useful if, for example, you'd like to save a long path as a variable, then pass it to multiple commands:

mikey@mikeys-thinkpad:~$ ldir=/usr/share/common-licenses/
mikey@mikeys-thinkpad:~$ ls $ldir
Apache-2.0  Artistic  BSD  CC0-1.0  GFDL  GFDL-1.2  GFDL-1.3  GPL  GPL-1  GPL-2  GPL-3  LGPL  LGPL-2  LGPL-2.1  LGPL-3  MPL-1.1  MPL-2.0
mikey@mikeys-thinkpad:~$ head $ldir/Apache-2.0
                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/
                        
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
mikey@mikeys-thinkpad:~$ cp $ldir/Apache-2.0 apache-2-license.txt

Turning Shell Variables into Environment Variables

You can also export variables. If you do this, programs you run from the shell will be able to read and use their values (E.G. to control what log messages are printed, whether error messages are printed in colour, etc.

mikey@mikeys-thinkpad:~$ python -c 'import os; print(os.getenv("MY_VAR"))' # MY_VAR is not set
None
mikey@mikeys-thinkpad:~$ MY_VAR=test python -c 'import os; print(os.getenv("MY_VAR"))' # MY_VAR is set for this command
test
mikey@mikeys-thinkpad:~$ export MY_VAR=test # MY_VAR will be set for every command started from this shell
mikey@mikeys-thinkpad:~$ python -c 'import os; print(os.getenv("MY_VAR"))' # So it will be set here
test

Here we've used Python to print the value of the environment variable MY_VAR from within the Python subprocess.

Footnotes

  1. Actually, bash includes methods for working with numbers and arrays, but they're not standard in every shell.