引言:为什么掌握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命令行是一个渐进的过程,关键在于:
- 理解基础:熟练掌握文件操作、文本处理和权限管理
- 组合命令:学会使用管道和重定向将简单命令组合成强大工具
- 编写脚本:将重复性任务自动化,从简单脚本开始
- 善用工具:利用历史命令、别名、快捷键提升效率
- 安全第一:理解命令的危险性,特别是删除和修改操作
- 持续实践:每天使用命令行,遇到问题先思考如何用命令解决
推荐的学习路径
- 第一周:掌握基础文件操作和文本查看命令
- 第二周:学习grep、find和基本的管道组合
- 第三周:尝试编写简单的自动化脚本
- 第四周:学习awk、sed和正则表达式
- 持续:阅读优秀脚本,参与开源项目,解决实际问题
记住,最好的学习方法是解决问题。当你遇到重复性任务时,思考如何用Bash自动化它。随着时间的推移,你会发现命令行不仅是一个工具,更是一种思维方式。
