重定向是 Shell 的核心特性之一,它可以改变数据流的走向。把输出保存到文件、从文件读取输入、把错误信息单独处理,都离不开重定向。
用 > 把命令输出写入文件,会覆盖原有内容:
echo "Hello World" > output.txt
ls -l > filelist.txt
如果文件不存在,会自动创建。
用 >> 在文件末尾追加内容,不覆盖原有内容:
echo "第一行" > log.txt
echo "第二行" >> log.txt
echo "第三行" >> log.txt
log.txt 的内容:
第一行
第二行
第三行
日志文件通常用追加方式写入。
用 < 从文件读取输入:
while read line; do
echo "读取到:$line"
done < data.txt
统计文件的行数:
wc -l < data.txt
标准错误(文件描述符 2)可以单独重定向:
ls 不存在的文件 2> error.log
把错误信息写入 error.log,正常输出仍显示在屏幕。
ls / /notexist > output.txt 2> error.txt
正常输出到 output.txt,错误信息到 error.txt。
ls / /notexist > all.txt 2>&1
2>&1 表示把标准错误重定向到标准输出。注意顺序很重要:
# 正确:先重定向输出,再把错误指向输出
command > file.txt 2>&1
# 错误:错误还是输出到屏幕
command 2>&1 > file.txt
更简洁的写法:
command &> file.txt
把输出重定向到 /dev/null,相当于丢弃:
# 丢弃正常输出
command > /dev/null
# 丢弃错误输出
command 2> /dev/null
# 丢弃所有输出
command &> /dev/null
这在判断命令是否执行成功时很有用:
if grep -q "pattern" file.txt 2> /dev/null; then
echo "找到了"
fi
Here Document 用于在脚本中嵌入多行文本:
cat << EOF
这是第一行
这是第二行
变量值:$HOME
EOF
运行结果:
这是第一行
这是第二行
变量值:/home/user
<< 后面是结束标记,可以任意命名,常用 EOF 或 END。
用单引号包住结束标记,变量不会被解析:
cat << 'EOF'
变量不会被解析:$HOME
命令替换也不会执行:$(date)
EOF
运行结果:
变量不会被解析:$HOME
命令替换也不会执行:$(date)
<<- 会忽略行首的制表符,方便脚本缩进:
if true; then
cat <<- EOF
第一行
第二行
EOF
fi
注意只有制表符会被忽略,空格不会。
Here String 是 Here Document 的简化形式,用于传递单行字符串:
grep "pattern" <<< "这是一行测试文本"
read a b c <<< "1 2 3"
echo "a=$a, b=$b, c=$c"
运行结果:
a=1, b=2, c=3
Shell 默认打开三个文件描述符:
| 编号 | 名称 | 默认设备 |
|---|---|---|
| 0 | 标准输入 | 键盘 |
| 1 | 标准输出 | 屏幕 |
| 2 | 标准错误 | 屏幕 |
可以自定义文件描述符:
# 打开文件描述符 3 用于读取
exec 3< input.txt
# 从文件描述符 3 读取
read -u 3 line
echo "读取到:$line"
# 关闭文件描述符
exec 3<&-
> 覆盖写入,>> 追加写入< 从文件读取输入2> 重定向错误,&> 重定向所有输出/dev/null 丢弃输出<< EOF Here Document 多行文本<<< Here String 单行字符串