3.1 Bash scripting
Brace Expansion
❯ echo {1..5}
1 2 3 4 5
❯ echo {0..20..2}
0 2 4 6 8 10 12 14 16 18 20
❯ echo {a..f}
a b c d e f
❯ touch file{1..4}.txt
❯ ls
file1.txt file2.txt file3.txt file4.txt
❯ cp -p file.config{,.bak}
❯ ls
file.config file.config.bak
❯ echo {contents,paper,bilbiography}.md
contents.md paper.md bilbiography.md
❯ wget https://www.some-url.com/picture{1..8}.jpg
Command Substitution
Capture the output of a command, and store it in a variable.
var=$(command)
or
var=`command`
my_date=`date +%m-%d-%Y`
#OR
my_date=$(date +%m-%d-%Y)
echo "You accessed this date on $my_date"
Output
You accessed this date on 09-13-2023
Globbing
Globbing in Bash refers to how the shell interprets special characters such as *
, and ?
which are commonly used to match filenames. Bash itself cannot recognize regular expressions, instead we use tools like sed
and awk
. It is important to distinguish globbing and regex as they can be easily confused.
The question mark matches any single character while the asterisks matches zero or more characters.
❯ ls file?.txt
file1.txt file2.txt file3.txt file4.txt file5.txt
❯ ls file[1-3].txt
file1.txt file2.txt file3.txt
❯ ls *.txt
dep.txt file1.txt file2.txt file3.txt file4.txt file5.txt marks.txt
❯ ls file?+(.png|.txt)
file1.png file1.txt file2.png file2.txt file3.png file3.txt file4.png file5.png
Here Documents
Send multiple lines of text to a command or shell script.
command << [marker]
input
[marker]
❯ sort << END
∙ 3
∙ 2
∙ 4
∙ 1
∙ END
1
2
3
4
Here String
Send one line of text to a command or shell script.
❯ wc -c <<< "String with many characters"
28
❯ foo="bar"
❯ sed 's/a/A/' <<< "$foo"
bAr
Shell control and redirection
>&
, &>
, >>&
and &>>
: (read above also) Redirect both standard error and standard output, replacing or appending, respectively.
Additional
source
reads and executes the contents of a file as sets of commands in the current shell.
Here is a file called commands.txt
echo "Your current directory is `pwd`"
echo "The date is `date +%m-%d`"
❯ source commands.txt
Your current directory is /home/promptier/Desktop/bash
The date is 11-20
Note source script
is equivalent to . script
, not to be confused with ./script
, which runs the script as an executable file, launching a new shell to run it.
The type
command is useful to learn more about a command. If it is a shell built in, it will not have a man page, instead, read about it using man bash
.
❯ man source
No manual entry for source
❯ type source
source is a shell builtin
The $PATH
variable contains a list of directories the system checks before running a command. Instead of running /usr/bin/python3
, we can just run python3
because /usr/bin
is located in the path.
If you install a program that is not located in the $PATH
variable, you can add it with either of the following two ways:
export PATH=/the/file/path:$PATH $
#adds to the beginnning and will be checked first
#OR
export PATH=$PATH:/the/file/path
#adds to the end and will be checked last
Script Utilities
By default, tee
will overwrite files, use -a
to append:
command | tee -a file
Tee can also be useful when writing to a protected file.
echo "newline" | sudo tee -a secret.txt
It is called "tee" as it resembles the letter "T" as well as the T-splitter in plumming since it takes from STDIN and "splits" or writes to both STDOUT and files.
egrep
, fgrep
and rgrep
are the same as grep -E
, grep -F
, and grep -r
.
grep -F
is a fixed string, meaning you want the string to be passed verbatim, and not interpreted as special regex. Such as if the search includes a dot user.txt
that you don't want to be interpreted as a regex wildcard.
grep -E
is extended grep, which can be used for fancy expressions, like ()
for groups and |
for OR. Here we search for any line that starts with "fork" or "group".
❯ grep -E '^no(fork|group)' /etc/group
nogroup:x:65534:
If you used regular grep without the -E, you'd have to escape out the special characters or else they'd be searched literally.
grep '^no\(fork\|group\)' /etc/group
As another useful example, we search for PCI devices starting with either "ethernet" or "network" with an insensitive search.
❯ lspci | egrep -i 'ethernet|network'
00:19.0 Ethernet controller: Intel Corporation 82579LM Gigabit Network Connection (Lewisville) (rev 04)
03:00.0 Network controller: Intel Corporation Centrino Advanced-N 6205 [Taylor Peak] (rev 34)