linux数据流重定向


一、标准输入与标准输出

操作系统为上层应用提供了统一的接口,文件描述符就是其中的一个例子。所以,为便于理解,我们可以认为文件描述符代表具体的IO设备!

标准输入设备: 代码为0(/dev/stdin)
标准输出设备: 代码为1(/dev/stdout)
标准错误输出设备: 代码为2(/dev/stderr)

study@ubuntu:/dev$ ls -l | grep std
lrwxrwxrwx  1 root root          15 1114 14:53 stderr -> /proc/self/fd/2
lrwxrwxrwx  1 root root          15 1114 14:53 stdin -> /proc/self/fd/0
lrwxrwxrwx  1 root root          15 1114 14:53 stdout -> /proc/self/fd/1

# 这三个文件都是软链接文件

向标准输出设备输出的数据就是标准输出,从标准输入设备读入的数据就是标准输入!

编程时我们只需将数据输出到描述符为1的文件,就实现标准输出,剩下的工作交给操作系统去“内部消化”,最终输出到目的设备里边去。

#include <unistd.h>
# fd为文件描述符,若为0,表示从标准输入来读取,也就是从/dev/stdin读取
ssize_t read(int fd, void *buf, size_t count);

# fd为文件描述符,若为1,表示输出到标准输出,也就是输出到/dev/stdout
ssize_t write(int fd, const void *buf, size_t count);

#include <stdio.h>
# printf是库函数,里边的调用函数默认会将数据输出到/dev/stdoout 
int printf(const char *format, ...);

#include <error.h>
# error是库函数,里边的调用函数默认会将数据输出到/dev/stdoerr
void error(int status, int errnum, const char *format, ...);

前面看到 /dev/stdin、/dev/stdout、/dev/stderr 都是链接文件,它们指向的文件才是“真正的输出设备”。

试想,如果我们把链接指向的文件修改了,那会怎样呢?很显然,输出会输出到重新指定的文件,读也从指定的文件读!

二、重定向符号

上面讲到的直接修改输出输入设备可以实现数据的重定向。但这种方法是从根源上重定向数据,对系统影响会比较大。bash上的重定向符号则是较为好用方便的数据流重定向方法。

之所以强调是bash上的,是因为重定向符号是作为bash的输入并被bash解析的符号,脱离了bash它们将一无是处!

2.1 输出符号

下面以 ls -l > 1.txt 为例简单说明输出重定向的流程。bash 解析该命令:创建子进程 ls 并将 -l 参数传递给 ls 进程,ls 进程的标准输出数据传递给bash,bash 发现 > 这个符号,会将这些标准输出数据输出到指定的文件1.txt去!这就是标准输出重定向了!

root@ubuntu:~# ls -l > 1.txt
root@ubuntu:~# ls -l
total 8
-rw-r--r-- 1 root root  105 1115 19:42 1.txt
drwxr-xr-x 2 root root 4096 115 00:15 ext4
root@ubuntu:~#
root@ubuntu:~# cat 1.txt
total 4
-rw-r--r-- 1 root root    0 1115 19:42 1.txt
drwxr-xr-x 2 root root 4096 115 00:15 ext4

常见的重定向符号有>、>>、1>、1>>、2>、 2>>。常见用法与比较如下:

# >(1>) 或>>(1>>) 将本应该输出到标准输出设备的数据重定向到1.txt
study@ubuntu:~/Desktop$ echo "hello world" > 1.txt
study@ubuntu:~/Desktop$ cat 1.txt
hello world
study@ubuntu:~/Desktop$ echo "hello donghai" > 1.txt	# > 会覆盖原文件
study@ubuntu:~/Desktop$ cat 1.txt
hello donghai
study@ubuntu:~/Desktop$ echo "hello lufeng" >> 1.txt	# >> 追加数据到原文件
study@ubuntu:~/Desktop$ cat 1.txt
hello donghai
hello lufeng
# 2> 或 2>> 将本应该输出的标准错误设备的数据重定向到 2.txt
study@ubuntu:~$ find /home -name .bashrc				# Permission denied为错误信息
find: ‘/home/study/.gnupg’: Permission denied
/home/study/.bashrc
find: ‘/home/study/.local’: Permission denied
/home/test/.bashrc

study@ubuntu:~$ find /home -name .bashrc 2> 2.txt
/home/study/.bashrc
/home/test/.bashrc

study@ubuntu:~$ cat 2.txt
find: ‘/home/study/.gnupg’: Permission denied
find: ‘/home/study/.local’: Permission denied

study@ubuntu:~$ find /home -name .bashrc 2>> 2.txt		# 2>> 追加到原文件
/home/study/.bashrc
/home/test/.bashrc

study@ubuntu:~$ cat 2.txt
find: ‘/home/study/.gnupg’: Permission denied
find: ‘/home/study/.local’: Permission denied
find: ‘/home/study/.gnupg’: Permission denied
find: ‘/home/study/.local’: Permission denied

# 将本应该输出到标准输出设备跟标准错误设备的数据重定向到3.txt
study@ubuntu:~$ find /home -name .bashrc 1> 3.txt 2> 3.txt
# 发现数据丢失了
study@ubuntu:~$ cat 3.txt
/home/study/.bashrc
/home/test/.bashrc
/home/study/.local’: Permission denied

# 将本应该输出到标准输出设备跟标准错误设备的数据重定向到3.txt
study@ubuntu:~$ find /home -name .bashrc 1> 3.txt 2>&1
# 发现跟直接向终端输出的一样
study@ubuntu:~$ cat 3.txt
find: ‘/home/study/.gnupg’: Permission denied
/home/study/.bashrc
find: ‘/home/study/.local’: Permission denied
/home/test/.bashrc

# 所以,应该使用第二个方法
# 若不想向终端打印错误数据,可以使用这种方法,直接将数据丢弃
study@ubuntu:~$ find /home -name .bashrc 2> /dev/null
/home/study/.bashrc
/home/test/.bashrc

2.2 输入符号

就是 < 了!

开始介绍之前,先简单了解下 cat 这个程序。

NAME
       cat - concatenate files and print on the standard output

SYNOPSIS
       cat [OPTION]... [FILE]... 
             
DESCRIPTION
# 连接文件到标准输出设备,意思是说将文件内容输出到标准输出设备
       Concatenate FILE(s) to standard output.					
# 如果cat后不接文件名,cat程序将从标准输入设备读数据
       With no FILE, or when FILE is -, read standard input.

可见,cat 除了可以向标准输出设备输出数据,还可以从标准输入设备读入数据!除了cat外,像nl也有这样的功能,不信可以去查手册!

下面以 cat > 4.txt < .bashrc 为例,简单描述标准输入重定向的流程。bash解析命令:bash 创建 cat 子进程,bash 读取 .bashrc 并将数据“传递”给 cat,cat 读取处理之后“传递”回 bash,bash 又将数据重定向输出到 4.txt

# cat默认从键盘读入数据,并将输入数据输出到4.txt
study@ubuntu:~$ cat > 4.txt
hello world
# 这里按下 ctrl+d 离开
study@ubuntu:~$ cat 4.txt
hello world

# 重定向cat从.bashrc读入数据,并将读入的数据输出到4.txt
study@ubuntu:~$ cat > 4.txt < .bashrc
...........

# << 这个符号其实不是重定向输入,只是通知cat进程读到eof就该结束进程了!!!
study@ubuntu:~$ cat > 4.txt << "eof"
> 123
> 456
> eof
study@ubuntu:~$
study@ubuntu:~$ cat 4.txt
123
456

讨论

以上只是我对linux数据流重定向的简单看法,欢迎大家批评指正!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值