引言:为什么掌握Bash命令行至关重要

Bash(Bourne Again SHell)是Unix/Linux系统中最流行的命令行解释器,它不仅仅是一个工具,更是提升工作效率的利器。无论你是系统管理员、开发人员还是数据分析师,熟练掌握Bash都能让你事半功倍。本文将从基础命令入手,逐步深入到高级用法,通过详细的例子和记忆技巧,帮助你快速掌握命令行操作。

Bash的核心优势

  • 自动化任务:通过脚本批量处理文件、定时任务等
  • 高效文件操作:比图形界面更快地搜索、过滤和处理文件
  • 远程管理:通过SSH连接服务器进行管理
  • 编程基础:是学习Linux系统编程和DevOps的基础

基础命令:构建你的命令行词汇表

文件和目录操作:最常用的命令

1. ls - 列出目录内容

ls 是你最先接触的命令,用于查看目录中的文件和子目录。

# 基本用法
ls

# 详细列表(显示权限、大小、修改时间)
ls -l

# 显示所有文件,包括隐藏文件(以.开头的文件)
ls -a

# 按修改时间排序(最新的在最后)
ls -lt

# 按修改时间倒序(最新的在最前)
ls -ltr

# 显示文件大小以易读格式(K、M、G)
ls -lh

# 组合使用
ls -laht

记忆技巧:

  • -l = long(长格式)
  • -a = all(所有文件)
  • -h = human-readable(人类可读)
  • -t = time(按时间排序)
  • -r = reverse(反向)

2. cd - 切换目录

# 进入目录
cd /home/user/documents

# 返回上一级目录
cd ..

# 返回家目录
cd ~

# 返回之前的目录
cd -

# 绝对路径 vs 相对路径
cd /etc/nginx          # 绝对路径
cd ./scripts           # 相对路径

3. pwd - 显示当前目录

pwd  # 输出:/home/user/projects

4. mkdir - 创建目录

# 创建单个目录
mkdir new_folder

# 创建多级目录
mkdir -p project/src/components

# 创建带空格的目录名(需要引号)
mkdir "My Project"

5. rm - 删除文件或目录

# 删除文件
rm file.txt

# 删除目录及其内容(递归删除)
rm -r directory_name

# 强制删除(不提示确认)
rm -f file.txt

# 强制递归删除目录
rm -rf directory_name

# 删除前确认
rm -i file.txt

⚠️ 警告:rm -rf 是极其危险的命令,特别是当变量为空时,可能导致灾难性后果。永远不要在生产环境中直接运行 rm -rf / 或类似命令。

6. cp - 复制文件或目录

# 复制文件
cp source.txt destination.txt

# 复制目录(递归)
cp -r source_dir/ destination_dir/

# 复制并保留权限和时间戳
cp -p source.txt destination.txt

# 复制时显示进度
cp -v source.txt destination.txt

# 复制并创建备份
cp -b source.txt destination.txt

7. mv - 移动或重命名

# 重命名文件
mv oldname.txt newname.txt

# 移动文件到目录
mv file.txt /home/user/documents/

# 移动并覆盖(默认行为)
mv -i file.txt /home/user/documents/  # 覆盖前确认

# 移动多个文件
mv file1.txt file2.txt file3.txt /home/user/documents/

文件查看和处理:了解你的数据

8. cat - 连接并显示文件内容

# 查看文件内容
cat file.txt

# 查看多个文件
cat file1.txt file2.txt

# 显示行号
cat -n file.txt

# 显示非空行号
cat -b file.txt

# 显示特殊字符(制表符、换行符等)
cat -A file.txt

9. less 和 more - 分页查看文件

# 使用less查看大文件(推荐)
less large_file.log

# 在less中:
#   /pattern   - 向下搜索
#   ?pattern   - 向上搜索
#   n          - 下一个匹配
#   N          - 上一个匹配
#   q          - 退出
#   g          - 到文件开头
#   G          - 到文件结尾
#   :n         - 下一个文件
#   :p         - 上一个文件

# 使用more查看
more file.txt

10. head 和 tail - 查看文件开头和结尾

# 查看文件前10行
head file.txt

# 查看前20行
head -n 20 file.txt

# 查看文件后10行
tail file.txt

# 查看后20行
tail -n 20 file.txt

# 实时追踪文件新增内容(日志监控神器)
tail -f application.log

# 追踪多个文件
tail -f log1.log log2.log

# 追踪并显示行号
tail -n +1 -f application.log

11. grep - 强大的文本搜索工具

# 基本搜索
grep "error" application.log

# 忽略大小写
grep -i "error" application.log

# 显示行号
grep -n "error" application.log

# 反向匹配(不包含"error"的行)
grep -v "error" application.log

# 递归搜索目录中的文件
grep -r "function_name" /path/to/project/

# 使用正则表达式
grep -E "error|warning" application.log

# 统计匹配行数
grep -c "error" application.log

# 显示匹配的文件名
grep -l "error" *.log

# 高亮匹配
grep --color=auto "error" application.log

权限管理:理解Linux安全模型

12. chmod - 修改文件权限

Linux权限分为读(r=4)、写(w=2)、执行(x=1),针对所有者、所属组、其他用户三类。

# 符号模式
chmod u+x script.sh      # 给所有者添加执行权限
chmod g-w file.txt       # 移除所属组的写权限
chmod o=r-- file.txt     # 设置其他用户为只读
chmod a+rwx directory/   # 给所有用户添加读写执行权限

# 数字模式
chmod 755 script.sh      # rwxr-xr-x (所有者读写执行,其他读执行)
chmod 644 file.txt       # rw-r--r-- (所有者读写,其他只读)
chmod 700 private_dir    # rwx------ (仅所有者可访问)
chmod 777 shared_dir     # rwxrwxrwx (所有人可读写执行,慎用!)

# 递归修改目录及其内容
chmod -R 755 directory/

13. chown - 修改文件所有者

# 修改所有者
chown user:group file.txt

# 递归修改目录所有者
chown -R user:group directory/

# 只修改所有者(不改变组)
chown user file.txt

# 只修改组
chown :group file.txt

中级技巧:组合命令提升效率

管道和重定向:命令组合的核心

管道 |

将一个命令的输出作为另一个命令的输入。

# 查看当前进程并筛选
ps aux | grep nginx

# 查找大文件并排序
du -sh * | sort -hr

# 统计行数
cat file.txt | wc -l

# 查看日志中的错误并统计
grep "error" application.log | wc -l

# 多个管道组合
cat access.log | grep "GET" | awk '{print $1}' | sort | uniq -c | sort -nr

重定向

# 标准输出重定向(覆盖)
command > output.txt

# 标准输出追加
command >> output.txt

# 标准错误重定向
command 2> error.txt

# 标准输出和错误都重定向
command > output.txt 2>&1
command &> output.txt

# 只重定向错误
command 2> /dev/null

# 丢弃所有输出
command > /dev/null 2>&1

文本处理三剑客:awk、sed、grep

14. awk - 强大的文本分析工具

# 打印第一列
awk '{print $1}' access.log

# 指定分隔符(默认是空格)
awk -F':' '{print $1}' /etc/passwd

# 条件过滤
awk '$3 > 1000' numbers.txt

# 计算总和
awk '{sum += $1} END {print sum}' numbers.txt

# 格式化输出
awk '{printf "User: %s, ID: %d\n", $1, $3}' users.txt

# 处理CSV
awk -F',' '{print $2}' data.csv

# 内置变量
awk 'NR==5' file.txt          # 打印第5行
awk 'END {print NR}' file.txt # 统计总行数

15. sed - 流编辑器

# 替换文本
sed 's/old/new/g' file.txt

# 直接修改文件(谨慎使用)
sed -i 's/old/new/g' file.txt

# 只替换每行第一个匹配
sed 's/old/new/' file.txt

# 删除行
sed '5d' file.txt                    # 删除第5行
sed '1,10d' file.txt                 # 删除1-10行
sed '/pattern/d' file.txt            # 删除包含pattern的行

# 插入和追加
sed '3i\插入的内容' file.txt         # 在第3行前插入
sed '3a\追加的内容' file.txt         # 在第3行后追加

# 多个命令
sed -e 's/foo/bar/g' -e 's/baz/qux/g' file.txt

查找文件:find 命令

16. find - 文件搜索神器

# 按名称查找
find /home -name "*.txt"
find /home -iname "*.txt"  # 忽略大小写

# 按类型查找
find /var -type f          # 普通文件
find /var -type d          # 目录
find /var -type l          # 符号链接

# 按大小查找
find / -size +100M         # 大于100MB
find / -size -10k          # 小于10KB
find / -size +1G -size -2G # 1GB到2GB之间

# 按时间查找
find /var -mtime -7        # 7天内修改过
find /var -atime +30       # 30天前访问过
find /var -ctime -1        # 24小时内状态改变

# 按权限查找
find /home -perm 644
find /home -perm /u+x      # 所有者有执行权限

# 组合条件
find /home -name "*.log" -size +1M -mtime -7

# 执行命令
find /tmp -name "*.tmp" -exec rm {} \;
find /home -name "*.bak" -delete

# 查找并显示详细信息
find /home -name "*.txt" -ls

高级用法:自动化和脚本编写

17. 变量和参数扩展

# 基本变量
name="John"
echo "Hello, $name"
echo "Hello, ${name}"

# 只读变量
readonly PI=3.14159

# 删除变量
unset name

# 位置参数
echo "Script: $0"          # 脚本名
echo "First: $1"           # 第一个参数
echo "Second: $2"          # 第二个参数
echo "All: $@"             # 所有参数
echo "Count: $#"           # 参数个数
echo "Last: ${!#}"         # 最后一个参数

# 参数扩展
filename="document.pdf"
echo "${filename%.pdf}"    # 移除后缀 → document
echo "${filename/.pdf/.txt}" # 替换后缀 → document.txt
echo "${filename:0:3}"     # 截取前3字符 → doc
echo "${#filename}"        # 长度 → 12
echo "${filename:-default}" # 如果未设置则用默认值

18. 条件判断和流程控制

# if 语句
if [ -f "/path/to/file" ]; then
    echo "文件存在"
fi

# 比较运算符
# 字符串比较
if [ "$a" = "$b" ]; then ... fi
if [ "$a" != "$b" ]; then ... fi
if [ -z "$a" ]; then ... fi      # 空字符串
if [ -n "$a" ]; then ... fi      # 非空字符串

# 数值比较(使用 (( )))
if (( a > b )); then ... fi
if (( a == b )); then ... fi
if (( a <= b )); then ... fi

# 文件测试
if [ -f "file.txt" ]; then ... fi      # 存在且是文件
if [ -d "directory" ]; then ... fi     # 孭在且是目录
if [ -r "file.txt" ]; then ... fi      # 可读
if [ -w "file.txt" ]; then ... fi      # 可写
if [ -x "file.txt" ]; then ... fi      # 可执行
if [ -s "file.txt" ]; then ... fi      # 非空
if [ -e "file.txt" ]; then ... fi      # 存在

# 逻辑运算
if [ "$a" -gt 10 ] && [ "$b" -lt 20 ]; then ... fi
if [ "$a" -gt 10 ] || [ "$b" -lt 20 ]; then ... fi

# case 语句
case "$1" in
    start)
        echo "Starting service..."
        ;;
    stop)
        echo "Stopping service..."
        ;;
    restart)
        echo "Restarting service..."
        ;;
    *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
        ;;
esac

19. 循环结构

# for 循环
for i in {1..10}; do
    echo "Number: $i"
done

# 遍历文件
for file in *.txt; do
    echo "Processing $file"
done

# C-style for
for ((i=0; i<10; i++)); do
    echo $i
done

# while 循环
count=1
while [ $count -le 10 ]; do
    echo $count
    ((count++))
done

# 读取文件行
while IFS= read -r line; do
    echo "Line: $line"
done < input.txt

# until 循环(与 while 相反)
count=1
until [ $count -gt 10 ]; do
    echo $count
    ((count++))
done

# break 和 continue
for i in {1..10}; do
    if [ $i -eq 5 ]; then
        continue  # 跳过当前迭代
    fi
    if [ $i -eq 8 ]; then
        break     # 退出循环
    fi
    echo $i
done

20. 函数

# 定义函数
function greet() {
    echo "Hello, $1!"
}

# 调用函数
greet "Alice"

# 返回值(通过return状态码)
function file_exists() {
    if [ -f "$1" ]; then
        return 0  # 真
    else
        return 1  # 假
    fi
}

if file_exists "/etc/passwd"; then
    echo "File exists"
fi

# 局部变量
function calculate() {
    local result=$(( $1 + $2 ))
    echo $result
}

# 函数返回字符串
function get_filename() {
    echo "output.txt"
}

filename=$(get_filename)

21. 数组

# 定义数组
fruits=("apple" "banana" "cherry")

# 访问元素
echo ${fruits[0]}      # apple
echo ${fruits[1]}      # banana
echo ${fruits[@]}      # 所有元素

# 获取长度
echo ${#fruits[@]}

# 遍历数组
for fruit in "${fruits[@]}"; do
    echo $fruit
done

# 动态添加元素
fruits+=("orange")

# 关联数组(需要bash 4+)
declare -A user
user["name"]="John"
user["age"]="30"
echo ${user["name"]}

22. 进程管理

# 查看进程
ps aux | grep nginx

# 杀死进程
kill 1234              # 优雅终止
kill -9 1234           # 强制终止
pkill nginx            # 按名称杀死
killall nginx          # 按名称杀死所有

# 后台运行
command &              # 后台运行
jobs                   # 查看后台任务
fg %1                  # 前台任务1
bg %1                  # 后台任务1

# nohup(退出终端后继续运行)
nohup ./long_running_script.sh &

实用脚本示例:解决实际问题

示例1:日志分析脚本

#!/bin/bash

# 分析Nginx访问日志,找出访问最多的IP
LOG_FILE="/var/log/nginx/access.log"
OUTPUT_FILE="top_ips.txt"

if [ ! -f "$LOG_FILE" ]; then
    echo "Error: Log file $LOG_FILE not found!"
    exit 1
fi

echo "Analyzing $LOG_FILE..."
echo "Top 10 IP addresses by request count:"

# 使用awk提取IP,统计频率,排序
awk '{print $1}' "$LOG_FILE" | sort | uniq -c | sort -nr | head -10 > "$OUTPUT_FILE"

cat "$OUTPUT_FILE"

# 找出访问最多的URL
echo -e "\nTop 10 URLs:"
awk '{print $7}' "$LOG_FILE" | sort | uniq -c | sort -nr | head -10

示例2:备份脚本

#!/bin/bash

# 自动备份指定目录并压缩

SOURCE_DIR="$1"
BACKUP_DIR="/backup"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="backup_${DATE}.tar.gz"

# 参数检查
if [ -z "$SOURCE_DIR" ]; then
    echo "Usage: $0 <source_directory>"
    exit 1
fi

if [ ! -d "$SOURCE_DIR" ]; then
    echo "Error: Source directory $SOURCE_DIR does not exist!"
    exit 1
fi

# 创建备份目录
mkdir -p "$BACKUP_DIR"

# 执行备份
echo "Backing up $SOURCE_DIR to $BACKUP_DIR/$BACKUP_NAME..."
tar -czf "$BACKUP_DIR/$BACKUP_NAME" -C "$(dirname "$SOURCE_DIR")" "$(basename "$SOURCE_DIR")"

# 检查备份是否成功
if [ $? -eq 0 ]; then
    echo "Backup completed successfully!"
    echo "File: $BACKUP_DIR/$BACKUP_NAME"
    echo "Size: $(du -h "$BACKUP_DIR/$BACKUP_NAME" | cut -f1)"
else
    echo "Backup failed!"
    exit 1
fi

# 清理旧备份(保留最近7天)
find "$BACKUP_DIR" -name "backup_*.tar.gz" -mtime +7 -delete

示例3:系统监控脚本

#!/bin/bash

# 监控CPU、内存和磁盘使用率

# CPU使用率
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
CPU_USAGE=${CPU_USAGE%.*}  # 取整数部分

# 内存使用率
MEM_USAGE=$(free | grep Mem | awk '{printf("%.0f", $3/$2 * 100.0)}')

# 磁盘使用率(根分区)
DISK_USAGE=$(df / | grep / | awk '{ print $5 }' | sed 's/%//g')

# 阈值设置
CPU_THRESHOLD=80
MEM_THRESHOLD=80
DISK_THRESHOLD=90

# 检查并告警
if [ $CPU_USAGE -gt $CPU_THRESHOLD ]; then
    echo "ALERT: CPU usage is ${CPU_USAGE}% (threshold: ${CPU_THRESHOLD}%)"
fi

if [ $MEM_USAGE -gt $MEM_THRESHOLD ]; then
    echo "ALERT: Memory usage is ${MEM_USAGE}% (threshold: ${MEM_THRESHOLD}%)"
fi

if [ $DISK_USAGE -gt $DISK_THRESHOLD ]; then
    echo "ALERT: Disk usage is ${DISK_USAGE}% (threshold: ${DISK_THRESHOLD}%)"
fi

# 如果没有告警,显示正常状态
if [ $CPU_USAGE -le $CPU_THRESHOLD ] && [ $MEM_USAGE -le $MEM_THRESHOLD ] && [ $DISK_USAGE -le $DISK_THRESHOLD ]; then
    echo "System status: OK"
    echo "CPU: ${CPU_USAGE}%, Memory: ${MEM_USAGE}%, Disk: ${DISK_USAGE}%"
fi

高级技巧:提升效率的隐藏功能

23. 历史命令和快捷键

# 历史命令
history              # 显示历史
!123                 # 执行第123条历史命令
!!                   # 执行上一条命令
!string              # 执行最近以string开头的命令
!$                   # 上一条命令的最后一个参数
!*                   # 上一条命令的所有参数

# 搜索历史
Ctrl+R               # 反向搜索历史
Ctrl+S               # 正向搜索历史(需要stty -ixon)

# 快捷键
Ctrl+A               # 移动到行首
Ctrl+E               # 移动到行尾
Ctrl+U               # 删除到行首
Ctrl+K               # 删除到行尾
Ctrl+W               # 删除前一个单词
Ctrl+L               # 清屏
Ctrl+C               # 终止当前命令
Ctrl+Z               # 暂停当前进程
Ctrl+D               # EOF(退出shell)
Ctrl+P               # 上一条历史命令
Ctrl+N               # 下一条历史命令

24. 别名(Alias)

# 临时别名
alias ll='ls -la'
alias grep='grep --color=auto'

# 永久别名(添加到 ~/.bashrc)
echo "alias ll='ls -la'" >> ~/.bashrc
source ~/.bashrc  # 立即生效

# 查看所有别名
alias

# 删除别名
unalias ll

25. 命令替换

# 使用反引号(旧式)
echo "当前目录: $(pwd)"
echo "当前目录: `pwd`"

# 嵌套使用
echo "文件数: $(ls | wc -l)"

# 在变量中使用
current_date=$(date +%Y-%m-%d)
echo "Today is $current_date"

26. 进程替换

# 比较两个目录的差异
diff <(ls dir1) <(ls dir2)

# 查看多个日志文件
tail -f <(cat log1.log) <(cat log2.log)

27. Brace Expansion

# 创建多个文件
touch file{1..5}.txt
touch file{a,b,c}.txt

# 创建嵌套结构
mkdir -p project/{src,tests,docs}/{unit,integration}

# 序列
echo {1..10..2}  # 1 3 5 7 9(步长2)
echo {a..z}      # 所有小写字母

28. 算术运算

# 使用 (( ))
(( result = 10 + 5 ))
echo $result  # 15

# 使用 expr
result=$(expr 10 + 5)

# 使用 bc(支持小数)
result=$(echo "scale=2; 10 / 3" | bc)
echo $result  # 3.33

# 使用 let
let result=10+5
echo $result

29. 字符串处理

# 基本操作
string="Hello World"
echo ${#string}          # 长度:11
echo ${string:0:5}       # 截取:Hello
echo ${string:6}         # 从第6个字符开始:World
echo ${string/World/Bash} # 替换:Hello Bash
echo ${string//o/X}      # 全局替换:HellX Wxrld

# 大小写转换
echo ${string^^}         # 大写:HELLO WORLD
echo ${string,,}         # 小写:hello world

# 删除模式
echo ${string#Hello}     # 删除开头: World
echo ${string%World}     # 删除结尾: Hello

# 默认值
unset myvar
echo ${myvar:-default}   # default
myvar=""
echo ${myvar:-default}   # default(空字符串也视为未设置)
echo ${myvar-default}    # (空字符串不视为未设置)

30. 正则表达式基础

# 基本元字符
.    # 任意单个字符
*    # 0次或多次
+    # 1次或多次
?    # 0次或1次
^    # 行首
$    # 行尾
[]   # 字符集
[^]  # 反向字符集
|    # 或
()   # 分组

# grep 使用正则
grep "^root" /etc/passwd          # 以root开头的行
grep "bash$" /etc/passwd          # 以bash结尾的行
grep "[0-9]" file.txt             # 包含数字的行
grep "^[^0-9]" file.txt           # 不以数字开头的行
grep "error\|warning" log.txt     # 包含error或warning的行

# sed 使用正则
sed -n '/^pattern/p' file.txt     # 打印匹配行
sed 's/[0-9]//g' file.txt         # 删除所有数字

实用工具和技巧

31. 监控和调试

# 监控命令执行时间
time ls -R /home

# 调试脚本执行
bash -x script.sh          # 显示每一步执行的命令
bash -v script.sh          # 显示读取的每一行

# 脚本语法检查
bash -n script.sh          # 不执行,只检查语法

# 查看命令路径
which command
whereis command
type command

# 查看命令别名
type -a command

32. 压缩和解压

# tar
tar -czf archive.tar.gz file1 file2 dir/  # 创建压缩包
tar -xzf archive.tar.gz                   # 解压
tar -tzf archive.tar.gz                   # 查看内容

# zip
zip -r archive.zip directory/
unzip archive.zip

# gzip
gzip file.txt          # 压缩
gunzip file.txt.gz     # 解压
zcat file.txt.gz       # 查看压缩文件内容

33. 网络相关

# 检查网络连接
ping -c 4 google.com

# 查看网络接口
ifconfig
ip addr

# 查看路由
netstat -rn
ip route

# 查看端口占用
netstat -tuln | grep :80
ss -tuln | grep :80

# 下载文件
wget https://example.com/file.zip
curl -O https://example.com/file.zip

# 测试端口连通性
nc -zv example.com 80
telnet example.com 80

34. 用户和权限管理

# 查看当前用户
whoami
id

# 查看用户信息
id username
getent passwd username

# 切换用户
su - username
sudo command

# 查看用户组
groups username
getent group

# 修改密码
passwd username

35. 定时任务

# at(一次性任务)
echo "ls /home" | at now + 1 hour

# crontab(周期性任务)
crontab -e          # 编辑
crontab -l          # 列出
crontab -r          # 删除

# crontab 格式
# * * * * * command
# | | | | |
# | | | | +-- 星期几 (0-7, 0和7都是周日)
# | | | +---- 月份 (1-12)
# | | +------ 日期 (1-31)
# | +-------- 小时 (0-23)
# +---------- 分钟 (0-59)

# 示例
0 2 * * * /backup/backup.sh          # 每天2:00执行
*/15 * * * * /monitor/check.sh       # 每15分钟执行
0 0 * * 0 /cleanup/cleanup.sh        # 每周日0:00执行

总结:持续学习和实践

掌握Bash命令行是一个渐进的过程,关键在于:

  1. 理解基础:熟练掌握文件操作、文本处理和权限管理
  2. 组合命令:学会使用管道和重定向将简单命令组合成强大工具
  3. 编写脚本:将重复性任务自动化,从简单脚本开始
  4. 善用工具:利用历史命令、别名、快捷键提升效率
  5. 安全第一:理解命令的危险性,特别是删除和修改操作
  6. 持续实践:每天使用命令行,遇到问题先思考如何用命令解决

推荐的学习路径

  • 第一周:掌握基础文件操作和文本查看命令
  • 第二周:学习grep、find和基本的管道组合
  • 第三周:尝试编写简单的自动化脚本
  • 第四周:学习awk、sed和正则表达式
  • 持续:阅读优秀脚本,参与开源项目,解决实际问题

记住,最好的学习方法是解决问题。当你遇到重复性任务时,思考如何用Bash自动化它。随着时间的推移,你会发现命令行不仅是一个工具,更是一种思维方式。