当前位置:首页>Linux>Linux 三大特殊符号:引号 / 重定向 / 通配符 —— 一篇彻底搞懂(含 Bash 进阶玩法)

Linux 三大特殊符号:引号 / 重定向 / 通配符 —— 一篇彻底搞懂(含 Bash 进阶玩法)

  • 2026-10-11 07:14:55
Linux 三大特殊符号:引号 / 重定向 / 通配符 —— 一篇彻底搞懂(含 Bash 进阶玩法)

同样写一行命令,老司机和新手的区别,往往就藏在 '"`>>>2>&1*{} 这几个不起眼的符号里。这篇文章把 Linux shell 最常用的引号系列 / 重定向系列 / 通配符系列一次性梳理透,并补上 2026 年仍然好用的 Process Substitution / here-string / extglob / noclobber 等进阶姿势。

一、引号系列:' " ` 与不加引号

引号含义是否解析变量是否解析命令是否解析通配符
' ' 单引号所见即所得,原样输出❌❌❌
" " 双引号解析变量、命令替换,但不展开 {} 序列 / *✅✅❌
不加引号双引号能力 + 通配符 / 花括号展开✅✅✅
` ` 反引号优先执行反引号里的命令,把结果嵌入当前命令—✅—

1.1 经典对比实验

# 单引号:完全原样echo '`hostname`  user001  $(whoami)  $UID {1..5}'# `hostname` user001 $(whoami) $UID {1..5}# 双引号:解析 $变量 / $() / ``echo "`hostname`  user001  $(whoami)  $UID {1..5}"# demo-host user001 root 0 {1..5}# 不加引号:再额外展开通配符 / 花括号echo `hostname`  user001  $(whoami)  $UID {1..5}# demo-host user001 root 0 1 2 3 4 5

1.2 反引号 vs $()(推荐 $())

echo "今天是 `date +%F` "echo "今天是 $(date +%F)"# 等价,但可读性更好、可嵌套

老脚本里反引号很多,新脚本一律推荐 $(...):支持嵌套、不会被字体误读成单引号。

1.3 什么时候必须加单引号?

# 1) 防止 $ 被 shell 提前解析sed -i  's/$old/$new/g'  file.txt          # ✗ 变量会被替换sed -i  's/\$old/\$new/g'  file.txt        # ✓ 转义后才正确# 2) 包含 awk / grep 的复杂表达式awk  '{print $1, $NF}'  access.log         # ✓ 单引号包住整段grep  '^\s*#'   /etc/sshd_config           # ✓ 不被 shell 干扰

二、重定向:> >> 2> 2>&1 <<

"重定向" 三个字的本质:改变标准输入 / 输出 / 错误输出的去向。

2.1 三个标准流

流文件描述符默认指向
stdin(标准输入)0键盘
stdout(标准输出)1终端
stderr(标准错误)2终端

2.2 完整速查表

符号含义典型用途
> / 1>覆盖写入 stdout创建 / 清空文件
>> / 1>>追加写入 stdout写日志、追加配置
2>覆盖写入 stderr单独收集错误
2>>追加写入 stderr错误日志
&> / >&stdout + stderr 一起覆盖一锅端
&>>stdout + stderr 一起追加定时任务最常用
>file 2>&1stdout 重定向到 file,再让 stderr 跟随 1POSIX 通用写法
< / 0<从文件读 stdin配合 tr、xargs
<<EOFhere-doc,多行输入写配置、SQL
<<<"str"here-string,把字符串当 stdin配合 bc、while read

2.3 实验:标准输出 vs 错误输出

# 一个不存在的命令eco aaaa# -bash: eco: command not found       ← 这条信息走的是 stderr (2)eco aaaa >  out.log                   # stdout 没东西,stderr 仍然喷在屏幕上eco aaaa 2> err.log                   # 把错误吃到 err.logeco aaaa &> all.log                   # 全部吃掉

2.4 同时收集正确 & 错误输出(生产最高频写法)

# 方式 1:最容易理解cmd  >> app.log  2>> app.log# 方式 2:POSIX 经典 ★(脚本 / 定时任务必背)cmd  >> app.log  2>&1# 方式 3:Bash 简写cmd  &>> app.log

⚠️ 2>&1 一定要写在 >file后面,否则 stderr 会先继承终端再被重定向,等于没生效:

cmd 2>&1 >> app.log     # ✗ 错误顺序,stderr 仍然在屏幕cmd >> app.log 2>&1     # ✓ 正确顺序

2.5 把输出彻底丢掉

cmd > /dev/null 2>&1     # 不想看到任何输出cmd &> /dev/null         # Bash 简写

2.6 输入重定向 + xargs

echo "a b c d e f"  | xargs -n3# a b c# d e fxargs -n1 < hostlist.txt     # 把文件按行喂给后续命令

2.7 here-doc:向文件写多行

cat > config.ini <<EOF[server]host =192.0.2.10port =8080EOF

📌 EOF 只是约定俗成的"结束标记",写成 END / DONE 都行,两边不能有多余空格。

防止 here-doc 里的变量被解析

cat > tpl.txt <<'EOF'当前用户: $USER# 想原样保留 $USER 怎么办?EOF# 给 EOF 加单引号 → 不解析变量,保持模板原样

缩进友好版本 <<-

cat > script.sh <<-'EOF'#!/bin/bashecho "hello"EOF# <<- 会去掉每行开头的 Tab(注意是 Tab,不是空格)

2.8 进阶:Process Substitution <(...)>(...)

原文没讲,但写脚本几乎离不开。

# 直接对比两条命令的输出,不用先生成临时文件diff <(ls /etc) <(ls /backup/etc)# 同时写多个 "管道终点"echo "hello"  | tee >(wc -c) >(md5sum) > /dev/null

2.9 防误覆盖:noclobber 与 >|

set -o noclobber            # 打开后 > 不会再覆盖已存在文件echo hi > exists.txt        # ✗ 报错:cannot overwrite existing fileecho hi >| exists.txt       # ✓ 强制覆盖set + o noclobber            # 关掉

写关键备份脚本前,强烈建议set -o noclobber 加一层保险。


三、通配符(globbing):批量找文件神器

⚠️ 通配符 ≠ 正则!它只用来匹配文件名和命令行字符串。

3.1 常见符号

符号含义例子
*任意长度任意字符*.log
?任意单个字符?? 匹配两字符文件名
[abc]集合中任意一个[a-c].txt
[!abc] / [^abc]取反[!0-9]* 不以数字开头
{}brace expansion,由 shell 直接展开{1..10}{a,b,c}

3.2 花括号 —— 批量生成的"魔法"

echo {a..z}              # a b c ... zecho {1..10}             # 1 2 3 ... 10echo {01..10}            # 01 02 ... 10  ★ 等宽数字echo {1..10..2}          # 1 3 5 7 9     ★ 步长echo {a..z..2}           # a c e g i ...# 非连续,列表形式echo {alice,bob,carol}echo user-{alice,bob,carol}# user-alice user-bob user-carol

3.3 实用小技巧

# 🌟 一键备份(最经典的花括号妙用)cp config.yaml{,.bak}# 等价于:cp config.yaml config.yaml.bak# 一次性创建多个目录mkdir -p project/{src,bin,docs,tests/{unit,integration}}# 批量改后缀(mv 不支持通配,要循环)for f  in *.txt; domv "$f" "${f%.txt}.md"; done# 找出 /bin 下 2 个字符的命令ls -l  /bin/??

3.4 seq —— 类花括号的命令版

seq 1 10# 1 ... 10seq 1 3 10# 1 4 7 10  (起 步 止)seq -w 1 10# 等宽:01 ... 10seq -s, 1 5# 1,2,3,4,5

3.5 通配符 vs 正则(别再混淆!)

维度通配符(glob)正则(regex)
谁解释shell命令本身(grep / sed / awk)
用途匹配文件名匹配字符串
* 含义"任意多个任意字符""前一个字符重复 0 次或多次"
? 含义"任意一个字符""前一个字符出现 0 或 1 次"
. 含义字面意义 .任意单个字符

3.6 进阶:extglob 扩展通配(Bash 专属)

shopt -s extglobls  !(*.log)             # 除 .log 外所有文件ls  *.@(jpg|png|gif)     # 任意图片ls +(abc)               # 出现 1 次或多次 abc

Bash 4+ 还支持 globstar:shopt -s globstar 后 **/*.py 递归匹配所有 Python 文件。


四、把三类符号串起来的实战例子

4.1 定时任务模板(运维必背)

# crontab -e* * * * *  /opt/scripts/cleanup.sh  >> /var/log/cleanup.log  2>&102 * * *  /opt/scripts/backup.sh   &>> /var/log/backup.log

4.2 一键备份配置目录

ts=$(date +%F)tar -I 'zstd -T0' -cf  "/backup/etc-${ts}.tar.zst" /etc/  \    >> /var/log/backup.log 2>&1

4.3 批量初始化用户家目录

for u in {user001..user010}; domkdir -p /home/$u/{bin,logs,data}chown -R $u:$u /home/$udone

4.4 here-doc 写 Nginx 配置

cat > /etc/nginx/conf.d/demo.conf <<'EOF'server {    listen 80;    server_name demo.example.com;    root  /var/www/demo;    access_log /var/log/nginx/demo.access.log;}EOFnginx -t && systemctl reload nginx

五、避坑清单(生产建议)

  1. ✅ 变量带空格一律加双引号:rm -rf "$dir",否则 rm -rf / 真的会发生

  2. ✅ 2>&1 永远跟在 >file后面

  3. ✅ > 会覆盖原文件,追加请用 >>;脚本前 set -o noclobber 更稳

  4. ✅ 大输出不要 > 一个被 tail -f 的文件,可能引起 logrotate 异常

  5. ⚠️ 通配符 *不匹配以 . 开头的隐藏文件,需要 shopt -s dotglob

  6. ⚠️ {1..10000000} 这种brace expansion 会占内存,慎用,超大序列改用 seq + 管道

  7. ⚠️ here-doc 的结束标记不能缩进(除非用 <<- 且只缩进 Tab)

  8. ⚠️ 反引号 ` ` 不能嵌套,改用 $()


六、数据脱敏说明

文中主机名 / 用户名 / 文件名 / IP 均为通用示例,与任何真实环境无关:

字段脱敏写法
主机名demo-host(原稿中 oldboy-aliyun-servers、oldboy-85-vip-king-v2 等已隐去)
用户名user001 / alice / bob / carol
文件名config.yaml / demo.conf / out.log 等无业务含义示例
IP192.0.2.10(RFC 5737 文档段)
域名demo.example.com(IANA 保留示例域名)

转发前可用 sed -E 批量替换:

sed -E 's/([0-9]{1,3}\.){3}[0-9]{1,3}/192.0.2.x/g'  raw.log > safe.log

七、一句话总结

单引号原样输出、双引号解析变量、反引号 / $() 先执行;> 覆盖、>> 追加、2>&1 合并、&>> 简写;* 找文件、{} 造序列、? 顶一字符。把这三类符号串起管道 |,就是 Linux shell 的"工业能力"。

如果对你有帮助,欢迎点赞 / 在看 / 转发给身边正在啃 Bash 的同学 。

最新文章

随机文章