Linux基本命令之I/O重定向和管道

发布时间 2023-11-29 15:56:09作者: 姑苏寒钟

I/O重定向,即输入/输出重定向,是指把命令行的输入重定向为从文件中获取内容,也可以把命令行的输出结果重定向到文件中。

1.标准输入、标准输出和标注错误
输出主要有两种:一种是程序运行的结果,即该程序生成的数据;一种是状态和错误信息。
我们知道,UNIX的思想是“一切都是文件”,类似ls的程序实际上也是把运行结果发送到了一个成为标准输出(standard output, stdout)的特殊文件中,状态信息则发送到一个称为标准错误(standard error, stderr)的文件中。默认情况,这两个文件都被链接到屏幕上,并且不会保存在磁盘文件中。
另外,许多程序从一个称为标准输入(standard input, stdin)的设备来得到输入,标准输入默认链接到键盘。

1.1 标准输出重定向
使用重定向操作符">",后面接文件名,就可以把标准输出重定向到另一个文件中,若文件不存在,则创建文件;若文件存在,则从文件的首位置开始覆盖文件。
例如

$ ls -l ./ > ls-output.txt
$ less ls-output.txt

输出

total 8
-rw-rw-r-- 1 lixj lixj 0 Jun 3 18:18 ls-output.txt
-rw-rw-r-- 1 lixj lixj 100 Jun 3 17:59 ls.txt
-rw-rw-r-- 1 lixj lixj 210 Jun 3 18:02 test1.txt
ls-output.txt (END)

如果不希望覆盖之前的文件,可以使用重定向操作符">>"来实现,例如

$ ls -l ./ >> ls-output.txt
$ less ls-output.txt

输出为

total 8
-rw-rw-r-- 1 lixj lixj 0 Jun 3 18:20 ls-output.txt
-rw-rw-r-- 1 lixj lixj 100 Jun 3 17:59 ls.txt
-rw-rw-r-- 1 lixj lixj 210 Jun 3 18:02 test1.txt
total 12
-rw-rw-r-- 1 lixj lixj 159 Jun 3 18:20 ls-output.txt
-rw-rw-r-- 1 lixj lixj 100 Jun 3 17:59 ls.txt
-rw-rw-r-- 1 lixj lixj 210 Jun 3 18:02 test1.txt
ls-output.txt (END)

1.2 标准错误重定向
一个程序可以把生成的输出内容发送到任意文件流中,如果把这些文件流中的前三个分别对应标准输入文件、标准输出文件和标准错误文件,那么shell将在内部用文件描述符分别索引它们为0、1和2。即标准错误等同于文件描述符2。
所以可以使用如下表示方法来重定向标准错误

$ ls -l ./nothing/ 2> ls-error.txt

1.3 将标准输出和标准错误重定向到同一文件
$ ls -l ./nothing &> ls-output.txt

1.4 处理不想要的输出
命令执行后,如果我们不希望得到输出,系统提供了一种方法,即通过把输出重定向到一个称为/dev/null的特殊文件中来实现它。

$ ls -l ./nothing 2> /dev/null

1.5 标准输入重定向
cat:合并文件
cat命令读取一个或多个文件,并将它们复制到标准输出文件中,格式为:
cat [file...]

例如:

$ cat ls-output.txt

显示ls-output.txt文件中的内容.cat用来显示比较短的文件。其优点是把文件连接在一起显示。例如

$ cat *.txt

也可以将其合并在一起

$ cat *.txt > all.txt

如果只使用cat而不带任何参数,那么将等待标准输入(默认键盘)读取内容,直到Ctrl+D结束,并在标准输出文件,即屏幕中输出。

$ cat
12345

也可以将其重定向到文件中

$ cat > cat_test.txt
12345

cat也可以从标准输入重定向中获取输入,使用"<".

$ cat < cat_test.txt

2. 管道
命令从标准输入到读取数据,并将数据发送到标准输出的能力,是使用了名为管道的shell特性。使用管道操作符“|”可以把一个命令的标准输出传送到另一个命令的标准输入中。

commend1 | commend2

例如

$ ls -l ./ | less

以上代码即使用less分页显示任意命令的输出,并将其结果发送到标准输出

2.1 过滤器
管道经常用来对数据执行复杂的操作。也可以把多条命令合在一起构成一个管道。这种方式中用到的命令通常被称为过滤器(filter)。

sort: 排序,将输入排序
$ ls /bin /usr/bin | sort | less

以上代码将/bin和/usr/bin目录下所有可执行程序合并成一个列表,并且按照顺序排列,最后再查看这个列表。

uniq:报错或忽略文件中重复的行
uniq可以接受来自于标准输入或者一个单一文件名参数对应的已排好序的数据列表。默认情况下,该命令删除列表中所有重复行。因此,在管道中添加uniq命令,可以确保所有的列表都没有重复行。
例如
$ ls /bin/ /usr/bin/ | sort | uniq | less

如果反过来想查看重复的列表,可以增加参数-d

$ ls /bin/ /usr/bin/ | sort | uniq -d | less

wc:打印行数、字数和字节数
wc(字数统计,word count)命令用来显示文件中包含的行数、字数和字节数。
$ wc ls-output.txt

输出

1 9 57 ls-output.txt

可以使用-l参数限制只显示行数,我们查看已经排好序的列表中的条目数,可以

$ ls /bin/ /usr/bin/ | sort | uniq | wc -l

输出

1376

grep:打印匹配行
它用来在文件中查找匹配文本, 使用方法为
grep pattern [file...]

如果想让我们从列出的程序中搜索出文件名包含zip的所有文件,

$ ls /bin /usr/bin | sort | uniq | grep zip

输出

bunzip2
bzip2
bzip2recover
funzip
gpg-zip
gunzip
gzip
unzip
unzipsfx
zipdetails
zipgrep
zipinfo

grep有用的两个选项为:-i,该选项使得grep在搜索时忽略大小写;-v,该选项使得grep只输出和模式不匹配的行.

head/tail:打印文件的开头部分/结尾部分
head命令将输出文件的前10行,tail命令则输出文件名的最后10行。也可以通过-n参数来修改输出的行数
$ head -n 5 ls-output.txt
$ tail -n 5 ls-output.txt

也可用于管道中

$ ls /usr/bin | tail -n 5

以上代码输出最后5个程序(往往是z开头的)
tail可以使用-f参数来实时查看文件.