Linux:Bash
Lecture 1
General
BASH stands for the Bourne Again SHell.
[root@ubuntu ~]# echo "Hello world" Hello world [root@ubuntu ~]# echo Hello\ world Hello world
An environment variable is used to store the location to search for programs on the system:
[root@ubuntu ~]# echo $PATH /root/.local/bin:/root/bin:/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin
Find out where which tool will be run and where it is:
[cloud-user@ubuntu ~]$ which echo /usr/bin/echo
Print the current path you're in:
[cloud-user@ubuntu ~]$ pwd /home/cloud-user
Change directory to your home folder:
[cloud-user@ubuntu ~]$ cd ~
Change directory to your previous direcory:
[cloud-user@ubuntu log]$ cd -
Show parameters for a tool. Supported by most tools:
[cloud-user@ubuntu ~]$ ls --help
Triple dot means 1 or more and the square brackets mean optional:
[cloud-user@ubuntu ~]$ ls --help Usage: ls [OPTION]... [FILE]...
Values with dashes prepended are called flags.
-a, --all do not ignore entries starting with .
Anything that doesn't take a value of flag is called an option
--color[=WHEN] colorize the output; WHEN can be 'always' (default
if omitted), 'auto', or 'never'; more info below
To list files in a column and give additional information:
[cloud-user@ubuntu log]$ ls -l
Permissions
-rw-rw----. 1 root utmp 384 Mar 15 10:34 btmp-20230401 drwxr-x---. 2 chrony chrony 6 Nov 14 16:24 chrony
the first value stands for either a file or directory.
d = directory; - = file.
The following values are the permissions for the file.
The first 3 are values for the owner that owns this file/directory. The second group is for the group that owns this this file/directory. The third group is the permission for everyone.
r = read; w = write; x = execute.
Read means you can read the contents. Write means you may modify and save. Execute means allowed to execute.
Directory permissions:
Read means whether you are allowed to list the files in this directory.
Write for a directory means you are allowed to rename, create or remove files within that directory.
Execute on a directory means search. It basically permits you to cd into a directory.
When file is set to write but folder is not, you can empty the file but not delete it. As deleting means modifying the contents of the directory.
- in general means you do not have the permission.
Continue
Control+L lets you clear your terminal.
An input stream is what you input via the terminal. The output stream is the end-result of the input.
The left angle bracket means, rewire the input of the proceding program to be the contents of this file
The right angle bracket means, put the output of the preceding program into a file
[cloud-user@ubuntu ~]$ < file > file
Set the input of cat to be the contents of the file hello.txt.
[cloud-user@ubuntu ~]$ echo "Hello world" > hello.txt [cloud-user@ubuntu ~]$ cat < hello.txt Hello world
Input the hello.txt file into cat, and output the result into a new file.
[cloud-user@ubuntu ~]$ cat < hello.txt > hello2.txt [cloud-user@ubuntu ~]$ cat hello2.txt Hello world
>> to append contents to a file.
[cloud-user@ubuntu ~]$ cat < hello.txt >> hello2.txt [cloud-user@ubuntu ~]$ cat hello2.txt Hello world Hello world
The | operator takes the output of the command of the left as the input, and sets it as the input stream of the command on the right.
[cloud-user@ubuntu ~]$ ls -l / | tail -n 1 drwxr-xr-x. 19 root root 4096 Feb 10 09:08 var [cloud-user@ubuntu ~]$ curl --head --silent google.com | grep -i content-length | cut --delimiter=' ' -f2 219
The root user is the administrator of the Linux system and can access any file even without permissions set for him.
The system folder does not contain files but kernel parameters. The core is basically the core of your machine.
The class folder contains different options to modify your system.
[cloud-user@ubuntu ~]$ ls /sys/ block bus class dev devices firmware fs hypervisor kernel module power [cloud-user@ubuntu class]$ pwd /sys/class
The # symbol means you are root. The $ symbol means you are not root.
When documentation online prepends a command with #, it means you need to run the command as root.
[cloud-user@ubuntu sys]$ sudo -i [root@ubuntu ~]#
The tee command takes standard input and writes to standard output. This can be the shell or a file.
The > parameter opens a shell as the current user. The current user does not have the right to modify the brightness file.
[cloud-user@ubuntu ~]$ sudo echo 1060 > brightness PERMISSION DENIED [cloud-user@ubuntu ~]$ echo 1060 | sudo tee brightness 1060
Lecture 2: Shell Tools and Scripting
https://www.youtube.com/watch?v=kgII-YWo3Zw
Define variables and using differing parentheses
[cloud-user@ubuntu ~]$ foo=bar [cloud-user@ubuntu ~]$ echo $foo bar [cloud-user@ubuntu ~]$ echo "Hello" Hello [cloud-user@ubuntu ~]$ echo 'World' World [cloud-user@ubuntu ~]$ echo "Value is $foo" Value is bar [cloud-user@ubuntu ~]$ echo 'Value is $foo' Value is $foo
$0 to $9 are reserved variables. $0 is the name of the script. The $1 through $9 variables will be the first through the ninth arguments pass to the script on executing it. $? gives you the error code from the previous command. $_ gives you the argument passed to the previous command. $# is the number of arguments given to the command. $$ is the process ID of the command that is running. $@ will expand to all arguments given.
A basic function looks like the following:
# File: mkcd.sh
mkcd() {
mkdir -p "$1"
cd "$1"
}
Load the functions within mkcd.sh to the shell with source and then call the function
$ source mkcd.sh $ mkcd hue $ pwd /home/cloud-user/hue
The || operator only executes the following command if the preceding command fails.
The && operator only executes the following command if the preceding command succeeds.
The ; operator always executes the following command.
$ false || echo "Oops fail" Oops fail $ true && echo "Things went well" Things went well $ true ; false ; echo "Things went well" Things went well
Basic example script
#!/bin/bash
echo "Starting program at $(date)" # Date will be substituted
echo "Running program $0 with $# arguments with pid $$"
for file in "$@"; do
grep foobar "$file" > /dev/null 2> /dev/null
# When pattern is not found, grep has exit status 1
# We redirect STDOUT and STDERR to a null register since we do not care about them
if [[ $? -ne 0 ]]; then
echo "File $file does not have any foobar, adding one"
echo "# foobar" >> "$file"
fi
done
Insert the result of a command into a variable and using command substitution
[cloud-user@ubuntu ~]$ tree=$(pwd) [cloud-user@ubuntu ~]$ echo "$tree" /home/cloud-user [cloud-user@ubuntu ~]$ echo "That $(pwd) looks beautiful" That /home/cloud-user looks beautiful
Process substitution is when a command is executed, and that output will be used as input for the preceding command.
$ cat <(ls) brightness hello.txt hello2.txt hue mkcd.sh
Using characters for filename expansion is called globbing.
The wildcard character looks for anything that matches.
The ? character replaces a single character
[cloud-user@ubuntu ~]$ ls *.txt hello.txt hello2.txt $ mkdir project1 project2 project11 project22 $ ls project? project1: project2:
Globbing variant with curly braces
$ touch file{1,2}
$ ls file?
file1 file2
$ touch project{1,2}/file{20,21}
$ ls project?/file??
project1/file20 project1/file21 project2/file20 project2/file21
$ mkdir jungle tree
$ touch {jungle,tree}/{a..k}
$ ls jungle/ tree/
tree/:
a b c d e f g h i j k
jungle/:
a b c d e f g h i j k
The shellcheck tool can be used to troubleshoot/debug shell scripts.
The tldr tool can be used for examples and summaries of other tools.
# dnf install ShellCheck $ shellcheck mkcd.sh # dnf install tldr $ tldr mv
The find command
# Look for files called "b", within the current subdirectory
$ find . -name b -type f
./jungle/b
./tree/b
# Find folder-names containing "project", within the current subdirectory
$ find . -name "project*" -type d
./project1
./project2
./project11
./project22
# Find and remove all files starting with name "file", within the current subdirectory
$ find . -name "file*" -type f -exec rm {} \;
# fd-find is an alternative to find. Its goal is to be faster and easier to use.
# dnf install fd-find
grep
Recursively look for "foobar" within the current subdirectory
# grep -R mkdir . ./.bash_history:man mkdir ./.bash_history:mkdir missing ./.bash_history:mkdir project1 project2 project11 project22 ./.bash_history:mkdir jungle bomb ./mkcd.sh: mkdir -p "$1"
Ripgrep is a recursive search tool which is an alternative to grep.
# dnf install ripgrep # Look for files that don't contain "cd" of any .txt file, exclude hidden files # rg -u --files-without-match "cd" -t txt hello2.txt hello.txt
Random tools
history is used to look at your current users' command history.
Ctrl+R is used to reverse-search commands.
# history 3 111 tldr mv 112 history 113 history 3 (reverse-i-search)`yum':
The tree command allows recursively listing directories in a 'pretty' fashion
# yum install tree $ tree -L 2 / [cloud-user@ubuntu ~]$ tree -L 1 . ├── brightness ├── hello.txt ├── hello2.txt ├── hue ├── huehuehue