Shell 脚本实用技巧汇总
Shell 脚本是把日常重复操作自动化的利器。本文整理了从基础到进阶最实用的知识点。
脚本骨架
bash
#!/usr/bin/env bash
set -euo pipefail # 严格模式
# -e: 任一命令失败立即退出
# -u: 使用未定义变量报错
# -o pipefail: 管道中任一环节失败则整个失败这三行放在脚本开头,能避免 80% 的坑。
变量与字符串
bash
name="World"
echo "Hello $name" # Hello World(双引号:变量展开)
echo 'Hello $name' # Hello $name(单引号:原样输出)
str="hello-world-foo"
echo ${str%-*} # hello-world(删除最后一个 - 后面的部分)
echo ${str%%-*} # hello
echo ${str#*-} # world-foo(删除第一个 - 及之前的)
echo ${str##*-} # foo
echo ${str/world/WORLD} # hello-WORLD-foo
echo ${str//o/0} # hell0-w0rld-f00(替换全部)
echo ${#str} # 15(字符串长度)
echo ${str:0:5} # hello(截取)条件判断
文件测试
bash
[ -f file ] # 存在且是普通文件
[ -d dir ] # 存在且是目录
[ -r file ] # 可读
[ -s file ] # 存在且非空
[ file1 -nt file2 ] # file1 比 file2 新数值比较
bash
[ $a -eq $b ] # 相等
[ $a -ne $b ] # 不等
[ $a -lt $b ] # 小于
[ $a -gt $b ] # 大于字符串比较
bash
[ "$str" = "abc" ] # 注意变量用双引号包裹!
[ -z "$str" ] # 空字符串
[ -n "$str" ] # 非空字符串坑:变量为空时
[ $str = "abc" ]会语法错误,务必加引号。
实用模式
安全遍历文件
bash
find . -type f -name "*.log" -print0 | while IFS= read -r -d '' file; do
echo "Processing: $file"
wc -l < "$file"
done默认值
bash
PORT="${PORT:-8080}" # 未设置则用 8080
MODE="${MODE:?MODE is required}" # 未设置则报错退出安全的临时文件
bash
cleanup() { rm -f "$TMPFILE"; }
trap cleanup EXIT
TMPFILE=$(mktemp)
echo "Working with $TMPFILE"检查命令是否存在
bash
if ! command -v docker &> /dev/null; then
echo "Error: docker is not installed"
exit 1
fi批量重命名
bash
for file in *.jpeg; do
[ -e "$file" ] || continue
mv "$file" "${file%.jpeg}.jpg"
done函数
bash
log() {
local level=$1
local message=$2
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$timestamp] [$level] $message"
}
log "INFO" "Server started"
log "ERROR" "Database connection failed"信号处理
bash
RUNNING=true
trap 'RUNNING=false; echo "Shutting down..."' SIGINT SIGTERM
while $RUNNING; do
echo "Working..."
sleep 1
done
echo "Cleanup done."调试技巧
bash
bash -x script.sh # 打印每条执行的命令
# 或在脚本中
set -x # 开始跟踪
set +x # 停止跟踪小结
Shell 脚本的三个习惯让你少踩坑:开头加 set -euo pipefail,变量永远加双引号,临时文件用 trap 清理。