Linux Shell Scripting Fundamentals
Script Execution Methods
Shell scripts are text files containing Linux commands executed by an interpreter.
Using sh
sh script.sh
Direct Execution
To execute a script directly:
- Begin the script with
#!/bin/bash - Grant execution permissions:
chmod u+x script.sh
./script.sh
This method internally uses the /bin/bash interpreter.
Common Symbols and Commands
- Command prompt ending with
$indicates a regular user;#indicates root (highest privileges) - In scripts,
#denotes comments - View shell version:
$SHELLor$0 - Root user ID is 0:
echo $UID - PS1 defines the command prompt format, e.g.,
PS1="\\e\\u@\\h~\\w"
Output Commands
echo: outputs text with newlineprintf: outputs text without newline
# Standard output with newline
echo hello world
# No newline
echo -n "hello world"
# With escape sequences
echo -e "\t\n"
# Colored output
echo -e "\e[1;42m hello world \e[0m"
# printf syntax similar to C
printf "%-20s\n" jack
File Operations
cat script.sh: view contentshead script.sh: view beginningtail -f script.sh: view end continuouslyvim script.sh: edit filetouch script.sh: create filels -l script.sh: detailed file info
Text Replacement
tr: replace characters
# Replace 'a' with 'b'
echo xxx | tr "a" "b"
# Convert lowercase to uppercase
echo "abc" | tr "a-z" "A-Z"
# Delete specific characters
echo "hello" | tr -d "l"
# Keep only digits
echo "abc123def" | tr -d -c "0-9"
Arithmetic Operations
let: perform calculations$((expression)): arithmetic expansionexpr: evaluate expressions
# Basic arithmetic
result=$((a + b))
# Floating point
echo "2*0.5" | bc
# Decimal precision
echo "scale=2;5/6" | bc
# Binary conversion
num=10
echo "obase=2;$num" | bc
# Square root
echo "sqrt(100)" | bc
# Exponentiation
echo "2^3" | bc
File Descriptors
- File descriptors are integers referring to open files
- 0: standard input, 1: standard output, 2: standard error
# Redirect standard output
echo "hello" > output.txt
# Append to file
echo "world" >> output.txt
# Redirect stderr to file
ls 2> error.txt
# Redirect stderr to stdout
ls 2>&1
# Discard stderr
ls 2>/dev/null
# Tee command
echo "data" | tee -a output.txt | cat
# Input redirection
cat < input.txt
# Here document
cat << EOF > log.txt
content here
EOF
# Custom file descriptor
exec 3<input.txt
exec 4>output.txt
File Checksums
- Generate checksums:
md5sum file1 file2 > checksum.md5 - Verify integrity:
md5sum -c checksum.md5
Example: generate checksums for all C file
find . -type f -name "*.c" -print0 | xargs -0 md5sum >> c.md5
Sorting
sort: sort lines- Combine with
uniqfor deduplication
# Sort numerically
sort -n data.txt
# Sort by column
sort -k 2 data.txt
# Reverse order
sort -r data.txt
# Dictionary order
sort -d data.txt
# Deduplicate
sort data.txt | uniq
# Count duplicates
sort -k 3 data.txt | uniq -c
Find Command
Find files recursively based on criteria:
# Basic usage
find ./ -maxdepth 3 -type f -name "*.txt"
# File types: f (file), d (directory), l (link)
# Time-based filters
find . -type f -name "*.c" -atime 7 # exactly 7 days ago
find . -type f -name "*.c" -atime +7 # older than 7 days
find . -type f -name "*.c" -atime -7 # newer than 7 days
# Size filters
find . -type f -size +20k # larger than 20KB
find . -type f -size -20k # smaller than 20KB
# Permission filters
find . -type f -perm 644
# Execute actions
find . -type f -name "*.py" -exec rm {} \;
find . -type f -name "*.py" -exec wc -l {} \;
Command Line Arguments
- Use
xargsto convert input into command-line arguments
# Default delimiter is whitespace
printf "a\nb\nc" | xargs -n 2 echo
# Custom delimiter
printf "a,b,c" | xargs -d , echo
# Replace placeholders
printf "a\nb" | xargs -I {} echo "{}"
# Process files with null delimiters
find . -type f -print0 | xargs -0 rm -f
File Permissions
- Modify permissions using
chmod
# Set specific permissions
chmod u=rwx,g=r,o=r script.sh
# Add execute permission for all
chmod a+x script.sh
# Remove write and execute for owner
chmod u-wx script.sh
# List all files with details
ls -la
Variables
Regular Variables
# Assign values
name='jack'
# Multi-line strings
pyCode='import os\nimport csv\nxxxx'
# Use variables
state="name is $name, current dir $(pwd)"
Environment Variables
Per-user
Edit ~/.bashrc:
export PATH=$PATH:/home/user/bin
export LD_LIBRARY_PATH=/usr/local/lib
Reload configuration:
source ~/.bashrc
System-wide
Edit /etc/profile:
export PATH=$PATH:/home/user/bin
Apply changes:
source /etc/profile
Script Parameters
# Pass arguments when running
./script.sh param1 param2
# Access parameters
$1, $2, ..., $9
${10}
# Total count
$#
# All parameters
$*
$@
# Last command exit status
$?
Conditional Statements
Test Conditions
# Numeric comparisons
-eq, -gt, -lt, -ge, -le
# String comparisons
=, ==, !=, -z (empty), -n (not empty)
# File tests
-e, -f, -d, -r, -w, -x
# Examples
if test 5 -gt 3; then
echo "true"
fi
if [[ $1 = '' ]]; then
echo "no params"
elif [[ $1 = 'lauf' ]] || [[ $1 = 'tom' ]]; then
echo "lauf or tom params"
else
echo "other params"
fi
# Short-circuit evaluation
[ $? -eq 0 ] && cd lauf
Loops
# Numeric range
for i in {1..5}; do
echo $i
done
# String iteration
IFS=";"
for i in "jack;lucy;lili"; do
echo $i
done
# Directory traversal
for file in *; do
echo $file
done
Functions
Functions resemble JavaScript syntax:
function func1() {
echo $1
echo $#
echo $@
}
func2() {
echo "func2"
}
# Call function
func1 "tom" 4
Practical Example
Recursive directory file creation:
#!/bin/bash
function addFile() {
if [ -d "$1" ]; then
echo "adding file to $1"
touch "$1/lauf.txt"
dealDir "$1"
fi
}
function dealDir() {
cd "$1"
curFiles=$(ls)
for item in $curFiles; do
addFile "$item"
done
}
dealDir "$1"