2. Introducing The Shell
Pattern Matching for Filenames
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| $ grep Linux chapter*
$ grep Linux chapter?
$ grep Linux chapter??
$ grep Linux chapter[12345]
$ grep Linux chapter[1-5]
$ grep Linux chapter*[02468]
$ ls [A-Z]*_*@
$ ls -1 /etc/*.conf
/etc/adduser.conf
/etc/appstream.conf
⋮
/etc/wodim.conf
|
The first is that the shell, not the invoked program, performs the pattern matching.
The second important point is that shell pattern matching applies only to file and directory paths.
Evaluating Variables
1
2
3
4
5
6
7
8
9
| $ printenv HOME
/home/smith
$ printenv USER
smith
$ echo My name is $USER and my files are in $HOME Evaluating variables
My name is smith and my files are in /home/smith
$ echo ch*ter9 Evaluating a pattern
chapter9
|
Where Variables Come From
1
2
3
4
5
6
7
8
9
10
11
12
| $ work=$HOME/Projects
$ cd $work
$ pwd
/home/smith/Projects
$ cp myfile $work
$ ls $work
myfile
$ work = $HOME/Projects The shell assumes "work" is a command
work: command not found
|
Variables and Superstition
1
2
3
4
5
| $ echo $HOME
/home/smith
# From echo’s perspective,
$ echo /home/smith
|
Patterns Versus Variables
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| $ ls
mammals reptiles
$ ls mammals
lizard.txt snake.txt
mv mammals/*.txt reptiles Method 1
FILES="lizard.txt snake.txt"
mv mammals/$FILES reptiles Method 2
$ echo mammals/*.txt
mammals/lizard.txt mammals/snake.txt
$ mv mammals/lizard.txt mammals/snake.txt reptiles
$ echo mammals/$FILES
mammals/lizard.txt snake.txt
$ mv mammals/lizard.txt snake.txt reptiles
$ mv mammals/$FILES reptiles
/bin/mv: cannot stat 'snake.txt': No such file or directory
FILES="lizard.txt snake.txt"
for f in $FILES; do
mv mammals/$f reptiles
done
|
Shortening Commands with Aliases
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| $ alias g=grep A command with no arguments
$ alias ll="ls -l" A command with arguments: quotes are required
$ ll # Runs "ls -l"
-rw-r--r-- 1 smith smith 325 Jul 3 17:44 animals.txt
$ g Nutshell animals.txt # Runs "grep Nutshell animals.txt"
horse Linux in a Nutshell 2009 Siever, Ellen
donkey Cisco IOS in a Nutshell 2005 Boney, James
# Shadowing the command
$ alias less="less -c"
# List a shell’s aliases
$ alias
alias g='grep'
alias ll='ls -l'
# See the value of a single alias
$ alias g
alias g='grep'
# Delete an alias from a shell
$ unalias g
|
1
2
3
| $ grep Perl animals.txt > outfile (displays no output)
$ cat outfile
alpaca Intermediate Perl 2012 Schwartz, Randal
|
1
2
3
4
5
| $ grep Perl animals.txt > outfile Create or overwrite outfile
$ echo There was just one match >> outfile Append to outfile
$ cat outfile
alpaca Intermediate Perl 2012 Schwartz, Randal
There was just one match
|
1
2
3
4
| $ wc animals.txt Reading from a named file
7 51 325 animals.txt
$ wc < animals.txt Reading from redirected stdin
7 51 325
|
1
2
3
4
5
6
7
8
9
10
| # Redirect stderr
$ cp nonexistent.txt file.txt 2> errors
$ cat errors
cp: cannot stat 'nonexistent.txt': No such file or directory
# Append stderr
$ cp nonexistent.txt file.txt 2> errors
$ cp another.txt file.txt 2>> errors
$ cat errors
cp: cannot stat 'nonexistent.txt': No such file or directory
cp: cannot stat 'another.txt': No such file or directory
|
1
2
3
4
5
6
| # Redirect both stdout and stderr
$ echo This file exists > goodfile.txt Create a file
$ cat goodfile.txt nonexistent.txt &> all.output
$ cat all.output
This file exists
cat: nonexistent.txt: No such file or directory
|
1
2
3
| $ wc < animals.txt > count
$ cat count
7 51 325
|
1
2
3
| $ grep Perl < animals.txt | wc > count
$ cat count
1 6 47
|
Disabling Evaluation with Quotes and Escapes
Single quotes tell the shell to treat every character in a string literally:
Double quotes tell the shell to treat all characters literally except for certain dollar signs and a few others:
1
2
3
4
| $ echo "Notice that $HOME is evaluated" Double quotes
Notice that /home/smith is evaluated
$ echo 'Notice that $HOME is not' Single quotes
Notice that $HOME is not
|
A backslash tells the shell to treat the next character literally:
1
2
3
4
5
6
7
8
9
10
11
| $ echo \$HOME
$HOME
$ echo "The value of \$HOME is $HOME"
The value of $HOME is /home/smith
$ echo 'The value of \$HOME is $HOME'
The value of \$HOME is $HOME
$ echo "This message is \"sort of\" interesting"
This message is "sort of" interesting
|
A backslash at the end of a line allows shell commands to span multiple lines:
1
2
3
| $ echo "This is a very long message that needs to extend \
onto multiple lines"
This is a very long message that needs to extend onto multiple lines
|
Final backslashes are great for making pipelines more readable:
1
2
3
4
5
6
| $ cut -f1 grades \
| sort \
| uniq -c \
| sort -nr \
| head -n1 \
| cut -c9
|
A leading backslash before an alias escapes the alias, causing the shell to look for a command of the same name, ignoring any shadowing:
1
2
3
| $ alias less="less -c" Define an alias
$ less myfile Run the alias, which invokes less -c
$ \less myfile Run the standard less command, not the alias
|
Locating Programs to Be Run
1
2
3
4
5
6
| $ ls -l /bin/ls
-rwxr-xr-x 1 root root 133792 Jan 18 2018 /bin/ls
$ cd /bin
$ ls ls
ls
|
1
2
| $ echo $PATH
/home/smith/bin:/usr/local/bin:/usr/bin:/bin:/usr/games:/usr/lib/java/bin
|
1
2
3
4
5
6
7
| $ echo $PATH | tr : "\n"
/home/smith/bin
/usr/local/bin
/usr/bin
/bin
/usr/games
/usr/lib/java/bin
|
To locate a program in your search path:
1
2
3
4
| $ which cp
/bin/cp
$ which which
/usr/bin/which
|
The more powerful (and verbose) type
command, a shell builtin that also locates aliases, functions, and shell builtins:
1
2
3
4
5
6
| $ type cp
cp is hashed (/bin/cp)
$ type ll
ll is aliased to ‘/bin/ls -l’
$ type type
type is a shell builtin
|
When the shell searches for a command by name, it checks if that name is an alias before checking the search path.
Environments and Initialization Files, the Short Version
1
2
3
4
| $ ls $HOME
apple banana carrot
$ ls -a $HOME
.bashrc apple banana carrot
|
# Set the search path
PATH=$HOME/bin:/usr/local/bin:/usr/bin:/bin
# Set the shell prompt
PS1='$ '
# Set your preferred text editor
EDITOR=emacs
# Start in my work directory
cd $HOME/Work/Projects
# Define an alias
alias g=grep
# Offer a hearty greeting
echo "Welcome to Linux, friend!"
Force a running shell to reread and execute $HOME/.bashrc with either of the following commands:
1
2
| $ source $HOME/.bashrc Uses the builtin "source" command
$ . $HOME/.bashrc Uses a dot
|
In real life, do not put all of your shell configuration in $HOME/.bashrc.