bash(一文讲透)

什么是 Bash?它为何值得你花时间学习?

在 Linux 和 macOS 系统中,你每天使用的终端,其实背后运行的是一套强大的脚本语言——Bash。这个名字源自 “Bourne-Again SHell”,是 Unix 系统中经典的命令行解释器。如果你经常在终端里敲命令,比如 ls、cd、grep,那其实你已经在用 Bash 了。但真正让 Bash 强大的,是它不仅能执行单条命令,还能把多个命令组合成自动化脚本,完成复杂任务。

想象一下,你每天都要备份一个项目文件夹,然后压缩成 zip,再上传到服务器。如果每次都手动敲一遍命令,一天两次还好,十天半个月后,你肯定会厌烦。而用 Bash 编写一个脚本,只需要运行一次,就能全自动完成整个流程。这就是 Bash 的价值:让重复劳动变得简单、可靠。

Bash 并不是编程语言的“高阶替代品”,而是一种“系统级自动化工具”。它特别适合处理文件操作、日志分析、部署脚本、定时任务等场景。掌握 Bash,等于掌握了一把打开系统底层逻辑的钥匙。


基础语法:从命令行到脚本文件

在开始写脚本前,先了解 Bash 的基本语法结构。Bash 脚本本质上是一系列命令的集合,保存为 .sh 文件,然后通过解释器执行。

创建一个简单的脚本文件

#!/bin/bash

echo "你好,世界!"

保存为 hello.sh,然后赋予执行权限:

chmod +x hello.sh

运行脚本:

./hello.sh

输出结果:

你好,世界!

⚠️ 注意:chmod +x 是给文件添加可执行权限,否则系统会拒绝运行。./ 表示当前目录下的文件,这是运行本地脚本的标准方式。


变量与参数:脚本中的“记忆库”

Bash 中的变量就像你手机里的记事本,可以临时存储信息。但和 Python 或 Java 不同,Bash 变量不需要声明类型,也不需要加 var 关键字。

定义和使用变量

#!/bin/bash

name="小明"
age=25

echo "我的名字是 $name,今年 $age 岁。"

输出结果:

我的名字是 小明,今年 25 岁。

传递参数给脚本

你还可以通过命令行向脚本传参,就像给函数传参数一样。

#!/bin/bash

echo "第一个参数是:$1"
echo "第二个参数是:$2"
echo "总共传入了 $# 个参数"

保存为 args.sh,运行:

./args.sh 你好 世界

输出:

第一个参数是:你好
第二个参数是:世界
总共传入了 2 个参数

💡 小技巧:$@ 表示所有参数的列表,$* 也是,但处理方式略有不同。建议初学者用 $@,更安全。


条件判断:让脚本“思考”

Bash 不只是按顺序执行命令,它还能根据条件做选择。这就像你在做决定时会问:“如果下雨,就带伞;否则就不带。”

if 语句的基本用法

#!/bin/bash

read -p "请输入你的年龄:" age

if [ $age -ge 18 ]; then
    echo "你已成年,可以投票。"
else
    echo "你还未成年,不能投票。"
fi

关键点说明:

  • [ ] 是测试命令,用于判断条件
  • -ge 表示“大于等于”(greater than or equal)
  • thenfi 是 if 语句的开始和结束标志
  • 一定要在 [] 两边加空格,否则会报错

多条件判断:elif 的使用

#!/bin/bash

read -p "请输入你的成绩(0-100):" score

if [ $score -ge 90 ]; then
    echo "优秀!"
elif [ $score -ge 80 ]; then
    echo "良好"
elif [ $score -ge 60 ]; then
    echo "及格"
else
    echo "不及格"
fi

这个例子展示了如何处理多个条件,结构清晰,逻辑明确。


循环结构:重复执行的魔法

在自动化任务中,重复是常态。Bash 提供了 forwhile 循环,让你轻松处理批量操作。

for 循环:遍历列表

#!/bin/bash

files=("file1.txt" "file2.txt" "file3.txt")

for file in "${files[@]}"; do
    # 检查文件是否存在
    if [ -f "$file" ]; then
        echo "找到文件:$file"
    else
        echo "未找到文件:$file"
    fi
done
  • files[@] 表示数组中所有元素
  • "$file" 加双引号是为了防止文件名含空格出错
  • dodone 是循环的起止

while 循环:条件满足就继续

#!/bin/bash

count=1

while [ $count -le 5 ]; do
    echo "第 $count 次循环"
    count=$((count + 1))
    # 使用 $(( )) 进行算术运算
    # 这里相当于 count = count + 1
done

输出:

第 1 次循环
第 2 次循环
第 3 次循环
第 4 次循环
第 5 次循环

实用技巧:文件与路径操作

Bash 在文件系统操作上极为强大。很多运维工作都依赖于它对文件的读写、查找、移动等操作。

检查文件是否存在

#!/bin/bash

filename="example.txt"

if [ -f "$filename" ]; then
    echo "$filename 存在,正在读取..."
    cat "$filename"
else
    echo "$filename 不存在。"
fi
  • -f 判断是否为普通文件
  • -d 判断是否为目录
  • -e 判断是否存在(文件或目录)

使用 find 查找文件

find . -name "*.log"

find . -size +1M

⚠️ 注意:find 命令非常强大,但要小心使用,避免误删重要文件。


实战案例:自动备份脚本

下面是一个完整的 Bash 脚本,实现自动备份项目文件夹。

#!/bin/bash


SOURCE_DIR="./project"
BACKUP_DIR="./backup"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILE="backup_$TIMESTAMP.tar.gz"

if [ ! -d "$SOURCE_DIR" ]; then
    echo "错误:源目录 $SOURCE_DIR 不存在。"
    exit 1
fi

if [ ! -d "$BACKUP_DIR" ]; then
    mkdir -p "$BACKUP_DIR"
fi

tar -czf "$BACKUP_DIR/$BACKUP_FILE" -C "$SOURCE_DIR" .

if [ $? -eq 0 ]; then
    echo "✅ 备份成功:$BACKUP_DIR/$BACKUP_FILE"
else
    echo "❌ 备份失败。"
    exit 1
fi

这个脚本展示了如何:

  • 使用变量管理路径和时间戳
  • if [ ! -d ] 检查目录是否存在
  • 使用 tar 命令压缩文件
  • 通过 $? 获取上一条命令的返回值(0 表示成功)
  • exit 1 中止脚本,避免后续错误

总结:Bash 是你不可忽视的工具

Bash 虽然不像 Python 或 JavaScript 那样“高大上”,但它在系统管理、自动化部署、日志处理等领域,依然是不可替代的存在。你不需要成为 Bash 专家,但至少要能写出能用、能运行的脚本。

从今天起,试着把那些重复的命令写成脚本。哪怕只是一个自动清理临时文件的小脚本,也能让你的开发效率提升一个台阶。

掌握 Bash,不是为了炫技,而是为了让你在面对复杂任务时,能多一种“自动化”的选择。它像一把瑞士军刀,看起来简单,却能在关键时刻解决问题。

当你能用几行 Bash 脚本,完成别人半小时的手动操作,你就真正理解了它的价值。

所以,别再只在终端里敲命令了。写一个脚本吧,让生活更轻松。