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)