INTERACTIVE LAB

systems0 次浏览 更新于 2026-09-30

Bash 脚本入门

从脚本执行、参数、条件、循环和退出码开始认识 Bash。

脚本是什么

Shell 就是把命令一条条执行。命令多了、还要按条件重复执行时,手动输入就很麻烦,于是把它们写进一个文本文件,这就是脚本。

最小的脚本通常有 Shebang、命令和注释:

#!/usr/bin/env bash

# 输出一行文字
echo "hello world"

保存为 test.sh 后,可以直接交给 Bash 执行:

bash test.sh

也可以加执行权限后直接运行:

chmod +x test.sh
./test.sh

#!/usr/bin/env bash 会从 PATH 中找到 Bash,比把路径写死成 /bin/bash 更灵活。脚本名是否使用 .sh 后缀不影响执行。

最小的变量用法

变量赋值时等号两边不能有空格,读取时加 $。路径和文本通常要加双引号:

name="小明"
echo "你好,$name"

脚本参数也可以直接读取:

echo "脚本名:$0"
echo "第一个参数:$1"
echo "参数数量:$#"

for item in "$@"; do
  echo "参数:$item"
done

$@ 要放在双引号里,才能保留参数中原有的空格。参数超过 9 个时,用 ${10} 这样的形式读取。需要逐个吃掉参数时,可以配合 shift:

while [ "$#" -gt 0 ]; do
  echo "当前参数:$1"
  shift
done

选项较多时,用 getopts 解析会比手写判断清楚:

while getopts "n:f:" opt; do
  case "$opt" in
    n) name="$OPTARG" ;;
    f) file="$OPTARG" ;;
    *) exit 2 ;;
  esac
done
shift "$((OPTIND - 1))"

条件判断

if 判断的其实是命令退出状态:返回 0 表示成功,其他值表示失败。

if [ -f "$1" ]; then
  echo "这是一个普通文件"
elif [ -d "$1" ]; then
  echo "这是一个目录"
else
  echo "路径不存在"
fi

[ 是 test 的另一种写法,括号和表达式之间必须有空格。Bash 专用的 [[ ... ]] 更宽松,还支持正则:

if [[ "$name" =~ ^[[:alpha:]]+$ ]]; then
  echo "看起来像一个英文名字"
fi

多值判断可以用 case:

case "$1" in
  start) echo "启动" ;;
  stop)  echo "停止" ;;
  *)     echo "用法:$0 {start|stop}" >&2; exit 2 ;;
esac

循环

for 适合遍历参数或列表,while 适合满足条件时反复执行,until 则是条件成功前反复执行:

for file in "$@"; do
  echo "$file"
done

count=0
while [ "$count" -lt 3 ]; do
  echo "$count"
  count=$((count + 1))
done

循环中可以用 break 提前结束,用 continue 跳过本轮。文件名遍历时要注意没有匹配项的情况;需要递归匹配时再考虑 globstar,不要把 glob 当成正则表达式。

退出码

每条命令都有退出码,$? 只能读取紧挨着的上一条命令:

cp "$source" "$target"
if [ "$?" -ne 0 ]; then
  echo "复制失败" >&2
  exit 1
fi

更常见的写法是直接把命令放进 if。脚本结束时可以用 exit 0 表示成功,用非零值表示失败。

if ! [ -r "$1" ]; then
  echo "文件不可读:$1" >&2
  exit 1
fi

&& 表示前一条成功后才执行,|| 表示前一条失败后才执行:

mkdir -p build && cd build || exit 1

直接执行脚本会在子 Shell 中运行;想让脚本修改当前 Shell 的变量或目录,需要使用 source script.sh(或 . script.sh)。调试时可以临时使用 bash -x script.sh 查看每条实际执行的命令。

DISCUSSION

评论 0

还没有评论,来留下第一条吧。