为什么你需要学习Shell脚本?
如果你在Linux上做过以下任何一件事:
· 重复输入同样的命令序列
· 手动备份文件,然后担心忘了
· 需要批量处理几十个文件
· 定期检查服务器状态
那么Shell脚本就是你的自动化利器。它能把复杂的操作变成一条命令,把重复劳动变成一键执行。
什么是Shell脚本?
简单说,Shell脚本就是把一系列Linux命令写在一个文件里,让计算机按顺序执行。就像做菜的食谱,一步步告诉系统该做什么。
你的第一个Shell脚本:Hello World
#!/bin/bash
# 这是我的第一个Shell脚本
# 显示欢迎信息
echo "Hello, World!"
echo "今天是:$(date)"
echo "当前用户:$(whoami)"
echo "当前目录:$(pwd)"
运行方法:
# 1. 保存为hello.sh
# 2. 添加执行权限
chmod +x hello.sh
# 3. 运行
./hello.sh
Shell脚本核心语法
1.变量:数据的容器
name="张三"
age=25
files=$(ls) # 把命令结果存到变量
2.条件判断:如果…那么…
if [ 条件 ]; then
# 做这件事
else
# 做那件事
fi
3.循环:重复做某件事
# for循环:遍历列表
for i in 1 2 3 4 5; do
echo "第$i次循环"
done
# while循环:条件满足就继续
while [ 条件 ]; do
# 重复执行
done
4.函数:可重用的代码块
function say_hello() {
echo "你好,$1"
}
say_hello "李四" # 调用函数
高频脚本实用案例
自动备份脚本,保留最近7天的备份
#!/bin/bash
# auto_backup.sh - 自动备份脚本
# 用法:./auto_backup.sh /要备份的目录
# 检查参数
if [ $# -eq 0 ]; then
echo "错误:请指定要备份的目录"
echo "用法:$0 /要备份的目录"
exit 1
fi
# 配置变量
SOURCE_DIR="$1" # 要备份的目录
BACKUP_DIR="/opt/backups" # 备份存放目录
DATE=$(date +%Y%m%d_%H%M%S) # 备份时间戳
BACKUP_NAME="backup_$(basename $SOURCE_DIR)_$DATE.tar.gz"
KEEP_DAYS=7 # 保留最近7天备份
# 创建备份目录
mkdir -p "$BACKUP_DIR"
echo "开始备份:$SOURCE_DIR"
# 执行备份
tar -czf "$BACKUP_DIR/$BACKUP_NAME" "$SOURCE_DIR" 2>/dev/null
# 检查是否成功
if [ $? -eq 0 ]; then
echo "✓ 备份成功:$BACKUP_NAME"
echo " 大小:$(du -h "$BACKUP_DIR/$BACKUP_NAME" | cut -f1)"
else
echo "✗ 备份失败!"
exit 1
fi
# 删除7天前的旧备份
echo "清理旧备份(保留最近${KEEP_DAYS}天)..."
find "$BACKUP_DIR" -name "backup_*.tar.gz" -mtime +$KEEP_DAYS -delete
# 显示备份列表
echo "当前备份文件:"
ls -lh "$BACKUP_DIR"/backup_*.tar.gz 2>/dev/null || echo "暂无备份"
使用方法:
# 备份网站目录
./auto_backup.sh /var/www/html
# 备份数据库(配合crontab定时执行)
# 每天凌晨2点备份
0 2 * * * /opt/scripts/auto_backup.sh /var/www/html
批量文件处理脚本
#!/bin/bash
# batch_file_processor.sh - 批量文件处理工具
# 功能:重命名、转换格式、批量压缩
# 显示菜单
show_menu() {
echo "========================================"
echo " 批量文件处理工具"
echo "========================================"
echo "1. 批量重命名文件(添加前缀/后缀)"
echo "2. 批量修改文件扩展名"
echo "3. 批量压缩图片(需要安装imagemagick)"
echo "4. 批量转换文本编码(GBK→UTF-8)"
echo "5. 批量查找并删除空文件"
echo "6. 批量统计文件大小"
echo "0. 退出"
echo "========================================"
}
# 批量重命名
batch_rename() {
echo -n "请输入要处理的目录:"
read dir
if [ ! -d "$dir" ]; then
echo "目录不存在!"
return
fi
echo -n "添加前缀(直接回车跳过):"
read prefix
echo -n "添加后缀(直接回车跳过):"
read suffix
echo "处理前预览:"
ls -1 "$dir" | head -10
echo -n "确认处理?(y/n): "
read confirm
if [ "$confirm" = "y" ]; then
cd "$dir"
count=0
for file in *; do
if [ -f "$file" ]; then
# 获取文件名和扩展名
filename="${file%.*}"
extension="${file##*.}"
# 新文件名
newname="${prefix}${filename}${suffix}.${extension}"
# 如果新名字不同才重命名
if [ "$file" != "$newname" ]; then
mv "$file" "$newname"
echo "重命名:$file → $newname"
((count++))
fi
fi
done
echo "完成!共处理 $count 个文件。"
fi
}
# 批量修改扩展名
change_extension() {
echo -n "请输入目录:"
read dir
echo -n "原扩展名(如txt):"
read old_ext
echo -n "新扩展名(如md):"
read new_ext
if [ ! -d "$dir" ]; then
echo "目录不存在!"
return
fi
count=0
for file in "$dir"/*.$old_ext; do
if [ -f "$file" ]; then
newname="${file%.*}.$new_ext"
mv "$file" "$newname"
echo "修改:$(basename $file) → $(basename $newname)"
((count++))
fi
done
if [ $count -eq 0 ]; then
echo "未找到 .$old_ext 文件。"
else
echo "完成!共修改 $count 个文件。"
fi
}
# 批量压缩图片
compress_images() {
if ! command -v convert &> /dev/null; then
echo "需要安装ImageMagick:sudo apt install imagemagick"
return
fi
echo -n "请输入图片目录:"
read dir
echo -n "压缩质量(1-100,建议80):"
read quality
if [ ! -d "$dir" ]; then
echo "目录不存在!"
return
fi
mkdir -p "$dir/compressed"
count=0
for img in "$dir"/*.{jpg,jpeg,png,gif}; do
if [ -f "$img" ]; then
filename=$(basename "$img")
convert "$img" -quality "$quality" "$dir/compressed/$filename"
old_size=$(stat -c%s "$img")
new_size=$(stat -c%s "$dir/compressed/$filename")
saved=$((100 - new_size * 100 / old_size))
echo "压缩:$filename (节省${saved}%)"
((count++))
fi
done
echo "完成!共压缩 $count 张图片,保存在 $dir/compressed/"
}
# 批量查找空文件
find_empty_files() {
echo -n "请输入目录:"
read dir
echo -n "是否删除空文件?(y/n): "
read delete
if [ ! -d "$dir" ]; then
echo "目录不存在!"
return
fi
echo "查找空文件..."
if [ "$delete" = "y" ]; then
find "$dir" -type f -empty -delete -print
echo "已删除空文件。"
else
find "$dir" -type f -empty -print
count=$(find "$dir" -type f -empty | wc -l)
echo "找到 $count 个空文件。"
fi
}
# 主循环
main() {
while true; do
show_menu
echo -n "请选择操作 (0-6): "
read choice
case $choice in
1) batch_rename ;;
2) change_extension ;;
3) compress_images ;;
4) echo "功能开发中..." ;;
5) find_empty_files ;;
6)
echo -n "请输入目录:"
read dir
du -sh "$dir"/*
;;
0)
echo "再见!"
exit 0
;;
*) echo "无效选择,请重新输入。" ;;
esac
echo ""
echo -n "按回车键继续..."
read
done
}
# 启动脚本
main
使用方法:
# 运行交互式菜单
./batch_file_processor.sh
# 单独使用某个功能
# 批量添加前缀
for file in *.jpg; do mv "$file" "vacation_$file"; done
# 批量转换大小写
for file in *; do mv "$file" "$(echo $file | tr 'A-Z' 'a-z')"; done
Shell脚本调试技巧
1.语法检查
bash -n script.sh # 只检查语法,不执行
2.详细执行过程
bash -x script.sh # 显示每一步执行过程
3.脚本安全检查
shellcheck script.sh # 需要安装shellcheck工具
最佳实践建议
1. 开头要有解释:前几行说明脚本用途、作者、版本
2. 变量使用引号:"$variable" 避免空格问题
3. 检查命令执行结果:if [ $? -eq 0 ]; then
4. 使用函数组织代码:提高可读性和复用性
5. 添加错误处理:set -e 让脚本遇到错误时退出
6. 记录日志:重要的操作要记录到日志文件