跟我一起学 Liunx 重定向和管道符

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 跟我一起学 Liunx 重定向和管道符

重定向

  • 标准输入重定向(STDIN,文件描述符为0) - 默认从键盘输入,也可从其他文件或命令中输入
  • 标准输出重定向(STDOUT,文件描述符为1) - 默认输出到屏幕
  • 错误输出重定向(STDERR,文件描述符为2) - 默认输出到屏幕

输出重定向

  • 输出重定向:将执行的命令所输出的内容,重定向到指定的文件内
  • 输出重定向符号分为以下几种

    • 正确输出重定向

      • 命令 > 文件 - 正确输出重定向(覆盖)

        • 命令 1> 文件 - 重定向中的标准输出模式,可以省略文件描述符1不写
      • 命令 >> 文件 - 正确输出重定向(追加)
    • 错误输出重定向

      • 命令 2> 文件 - 错误输入重定向(覆盖)

        • 错误输出模式的文件描述符2是必须要写的
      • 命令 2>> 文件 - 错误输入重定向(追加)
    • 共同输出重定向

      • 命令 &> 文件 - 正确和错误输出重定向到同一个文件(覆盖)

        • 另一种写法

          • 命令 > 文件 2>&1
      • 命令 &>> 文件 - 正确和错误输出重定向到同一个文件(追加)

        • 另一种写法

          • 命令 >> 文件 2>&1
          • 2>&1 是一个固定的格式,是覆盖还是追加,取决于前面的重定向是覆盖还是追加

正确输出重定向

将原本要显示在屏幕上的内容(命令返回的 状态码为0),输出到指定的文件中

一定要注意自己是需要追加还是覆盖,将文件内容覆盖,相当于自己把文件内容删了,毕竟 Linux 一切皆文件,执行重定向操作前,要有备份的习惯,误操作覆盖了,也能还原原来的内容

  • 利用正确输出重定向生成一个新的文件
  • 当我们不使用 > study.txt 这一部分,只使用 echo 'hello world' ,回车后,会在显示器上返回 hello world 这一段字符
  • 完成后,执行 cat study.txt 就可以看到文件的内容是 hello world
  • 但是如果存在 study.txt 这个文件时,多次执行下面的命令,文件内永远都只有 hello world 这一段内容
echo 'hello world' > study.txt
  • 将正确输出重定向追加到指定的文件
  • 执行了下面的命令后,我们查看(cat study.txt) 文件时,发现里面有两行内容,一行是前面覆盖 重定向写入的 hello world ,另一行就是这个时候插入的 good luck, have fun 这段内容
  • 每执行一次下面的命令,study.txt 文件内就会增加一行 good luck, have fun
  • 如果执行上面的 echo 'hello world' > study.txt ,那 study.txt 文件内就只有 hello world 一行内容了
echo 'good luck, have fun' >> study.txt
  • 配合 <<EOF 实现静态写入多行内容

    • 一般写入多行内容,都会使用 vim 或者 vi 这类文本编辑器去操作,但是写 shell 就需要去规避这一类的人为干预,重定向配合 <<EOF 就是一个很好的方法
    • <<EOFEOF 为结尾来结束文件内容的写入
同样也是要注意是覆盖还是插入的方式
  • 覆盖写入
cat <<EOF > study.txt
this is a test1
this is a test2
this is a test3
EOF
  • 追加写入
cat <<EOF >> study.txt
this is a test1 too
this is a test2 too
this is a test3 too
EOF
多次执行就可以看出效果和区别

错误输出重定向

将原本要显示在屏幕上的内容(命令返回的 状态码为非0),输出到指定的文件中

同样也是要注意需要使用的是覆盖还是追加

  • 本机 PATH 变量没有 whoami.bak 这个命令
  • 使用 which whoami.bak ,屏幕上会输出 /usr/bin/which: no whoami.bak in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)

    • 假设我写脚本,需要判断一个命令是否存在,但我有强迫症,我不想看到这些报错,我只想知道有没有,可以使用下面的方式,将错误输出重定向到 /dev/null 文件内,这个文件是一个黑洞文件,所有进入到这个文件的文件或目录,都会不复存在(比如 mv xxx.txt > /dev/null 相当于执行了rm -f 命令)
which whoami.bak 2> /dev/null
  • 将上面的命令,重定向到 study.txt 文件内

    • 分别为覆盖和追加,相信通过上面的操作,大家已经心里有了13数了
which whoami.bak 2> study.txt
which whoami.bak 2>> study.txt

共同输出重定向

将正确的和错误的输出都重定向到同一个文件内

同样也是要注意需要使用的是覆盖还是追加

  • 同样引用上面的案例,我需要去判断当前的 PATH 变量里面有没有我需要的命令,如果没有,我就执行其他的操作
  • $? 是用来判断上一条命令执行的状态为成功(返回状态码0)还是不成功(返回状态码为非0
  • 重定向操作是成功的,但是命令实际是属于错误输出的,此时的 $? 返回的状态码为非0
  • 命令操作是成功的,但是重定向操作时不正常的,$? 返回的状态码也是非0

    • 比如重定向的文件名称和目录名称一样,就会返回 Is a directory 的报错
# || 在 shell 中作为判断使用,表示的是 '或者' ,|| 前后只需要有一个命令可以正确执行即可
## whoami.bak 不存在,因此会返回 true
which whoami.bak &> /dev/null || echo "true"
## whoami 存在,因此不会返回 true
which whoami &> /dev/null || echo "true"

敲黑板

  • 无论是哪种输出重定向,一定要注意指向的文件,如果执行的文件是二进制文件,那二进制文件就会变成普通文件,可以通过 file 命令去比较
  • 重定向对目录类型的文件操作会返回 Is a directory 的报错
  • 输出重定向千万不要对块设备操作,比如磁盘,会导致数据被覆盖,后果很严重
  • 举个离(例)子(子) [离谱的例子]
备份一个 whoami 命令来玩,不能直接玩,不然命令就废了
cp /usr/bin/whoami{,.bak}
先查看 whoami.bak 文件的属性
file /usr/bin/whoami.bak
可以看到,是一个 ELF 文件,属于 executable 可执行文件
/usr/bin/whoami.bak: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=0cd50214a1dcf60ac187526884bb621ede7ef83a, stripped
咱们重定向一些内容给 whoami.bak

追加的情况下,不会影响文件本身的类型

echo 'this is a test' >> /usr/bin/whoami.bak
覆盖的情况下,文件本身的类型就会变为 ASCII text 文本文件
echo 'this is a test' > /usr/bin/whoami.bak
所以输出重定向所指定的文件一定要注意了,不要指定错了,不然后悔都来不及

输入重定向

  • 输入重定向:从文件内将内容重定向给命令
  • 这个例子比较奇葩,因为可以直接使用 cat study.txt 命令,这里是用来做一个理解使用的例子
cat < study.txt
  • 一般像 mysql 需要导入 sql 文件,就可以使用输入重定向的方式
mysql -u<user_name> -p<user_passworld> -h<mysql_host> -P<mysql_port> < xxx.sql

输入输出重定向

  • 输入输出重定向:将文件的内容输入重定向给命令后,将命令输出的内容重定向到指定的文件内
  • 命令 < 文件1 > 文件2 - 将文件1的输入重定向输出到文件2
  • 同样是一个不太恰当的例子,主要是用来理解思路的

    • 将 study.txt 文件内容输入cat 命令,再将 cat 命令输出的内容,输出到 study.txt.bak 文件内
    • 实际使用 cat study.txt > study.txt.bak 就可以了
cat < study.txt > study.txt.bak

字符串重定向

  • 字符串重定向:将字符串输入重定向给命令
  • 命令 <<< "字符串" - 字符串输入重定向
  • 以上的输入输出重定向,都是需要针对文件的情况下操作的,但是在写脚本的时候,遇到一些变量需要被引用,但是写 echo ${xxx} | awk '{print $1}' 又觉得没有13格,这个时候,就轮到字符串重定向上场了
先定义一个变量
test='hello world'
当我只想要得到 hello 这一个内容,我又不想用 echo,那就可以用字符串重定向的方式
# --color 参数是高亮过滤到的内容,有的 linux 发行版的 grep 命令默认不带这个参数
grep --color hello <<< ${test}
# 过滤 hello,我只要输出 hello
grep -o hello <<< ${test}
# awk 的形式
awk '{print $1}' <<< ${test}

管道符

进程管道

  • | 表示管道符,将管道符前面操作的输出转交给管道符后面的来操作和处理
  • 同样是一个奇葩的例子,用来便于理解

    • 实际直接使用 grep root /etc/passwd 就可以了
cat /etc/passwd | grep root
  • 123 木头人,不许说话不许动

    • 通过 echo 将 sleep 3 输出,然后交给 bash 执行
    • 实际直接使用 sleep 3 就可以了
echo "sleep 3" | bash

三通管道

  • tee 是一个命令,加上管道符,可以变成三通管道,将三通管道前面操作的输出做一个副本

    • 三通管道和正确输出重定向的区别在于,正确输出重定向不会在屏幕上显示输出的内容,直接写入指定的文件内;而三通管道会输出到屏幕上,并写入到指定的文件内
    • 三通管道和错误输出重定向的区别在于,错误输出重定向不会屏幕上显示输出的内容,直接写入指定的文件内;而三通管道会输出到屏幕上,并不会将错误内容写入到文件内,文件内容会被空内容覆盖
    • 所以三通管道属于覆盖重定向

      • 若为正确输出重定向,则将正确输出覆盖到指定文件内
      • 若为错误输出重定向,则将清空指定文件的内容
cat study.txt | tee study-bak.txt

参数传递

  • xargs 命令表示参数传递
  • Linux xargs 命令

    • xargs(英文全拼: eXtended ARGuments)是给命令传递参数的一个过滤器,也是组合多个命令的一个工具
    • xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据
    • xargs 也可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行
    • xargs 默认的命令是 echo,这意味着通过管道传递给 xargs 的输入将会包含换行和空白,不过通过 xargs 的处理,换行和空白将被空格取代
    • xargs 是一个强有力的命令,它能够捕获一个命令的输出,然后传递给另外一个命令
    • 之所以能用到这个命令,是由于很多命令不支持 | 进程管道来传递参数
  • xargs 参数

    • -a - file 从文件中读入作为 stdin
    • -e - flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止
    • -p - 当每次执行一个argument的时候询问一次用户
    • -n - num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的
    • -t - 表示先打印命令,然后再执行
    • -i - 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给 {},可以用 {} 代替
    • -r - no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了
    • -s - num 命令行的最大字符数,指的是 xargs 后面那个命令的最大命令行字符数
    • -L - num 从标准输入一次读取 num 行送给 command 命令
    • -l - 同 -L
    • -d - delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符
    • -x - exit的意思,主要是配合 -s 使用
    • -P - 修改最大的进程数,默认是 1,为 0 时候为as many as it can
  • 又是一个不太恰当的例子,主要用于理解

    • echo 命令无法获取通过 | 进程管道 传递的内容
ls | echo
  • 使用 | xagrs 后可以获取到 ls 传递的内容
ls | xargs echo
  • 多行内容通过 xargs 变成单行内容

    • 继续使用上面用到的 study.txt 文件
cat study.txt | xargs
  • 常用的 -i 或者 -I 参数,配合 {} 来指定参数传递的指定位置

    • 在当前路径下的 .txt 文件后面加上 -bak 的后缀
ls *.txt | xargs -i mv {}{,-bak}
{} 的位置决定了参数传递的位置
ls *.txt* | xargs -i echo "{} is a test"
ls *.txt* | xargs -i echo "test for {}"
相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
弹性计算 运维 Shell
Linux加强篇003-管道符、重定向与环境变量
山重水复疑无路,柳暗花明又一村
304 1
|
6月前
|
Linux C++
认识Linux指令之 “ 重定向” 符号
认识Linux指令之 “ 重定向” 符号
149 1
认识Linux指令之 “ 重定向” 符号
|
6月前
|
网络协议 Shell
使用输入输出重定向与管道命令——重定向
使用输入输出重定向与管道命令——重定向。
53 0
|
6月前
|
Linux Shell
使用输入输出重定向与管道命令——管道
使用输入输出重定向与管道命令——管道。
51 0
基本指令(2):通配符,重定向,命令行管道
基本指令(2):通配符,重定向,命令行管道
|
Linux 编译器
疯了!终于有人告诉我什么是重定向 管道命令 环境变量PATH!
FHS本质一套规定Linux目录结构,软件建议安装位置的标准。使用Linux来开发产品或者发布软件的公司、个人太多,如果每家公司或者个人都按照自己的意愿来配置文件或者软件的存放位置,这无疑是一场灾难。
98 0
|
Shell Linux 开发工具
Shell的基本信息、重定向与管道符
Shell的基本信息、重定向与管道符
149 0
Shell的基本信息、重定向与管道符
|
Java Linux Shell
Linux命令之通配符&管道符
Linux命令之通配符&管道符
|
Shell Linux 数据安全/隐私保护
大话Linux——管道符重定向和环境变量
3、管道符、重定向与环境变量 3.1、输入输出重定向 标准输入重定向(STDIN,文件描述符为0)默认从键盘输入,还可以从其他文件或命令输入 标准输出重定向(STDOUT,文件描述符为1):默认输出到屏幕 错误输出重定向(STDERR,文件描述符为2):默认输出到屏幕
134 0
|
网络协议 Shell Linux
09_Linux基础-SHELL-标准输入与标准输出-重定向-管道
SHELL-标准输入与标准输出-重定向-管道
208 0