本文是快乐学习Linux的第二篇,是基于Windows的Linux子系统(WSL)进行操作的。
适用于学习Linux系统查看命令帮助和重定向的读者。
Linux命令形式
Linux中,命令存在4种形式:
- type command:使用
type
命令能够显示命令的类别。
可执行程序
可执行程序位于/usr/bin
目录中,是利用编程语言编写程序编译的二进制文件,包括C/C++
、shell和python等编写的脚本。
- which command:显示
可执行程序
的位置。普通桌面系统可执行程序一般只有一个版本,但是在大型服务器中可能存在多个可执行程序版本,由此来确定准确位置 - command --help:许多可执行文件能够显示其语法和选项说明文档。某些程序可能不支持,但是不妨碍我们尝试一下。
- man program:在命令行运行的可执行程序往往会提供一个正式文档,使用man分页程序可以进行查看。man是使用less工具来显示的,所以可以使用less命令进行查看。
- apropos program:基于关键字匹配参考手册。是一种粗糙的查询手段,可以获得查询字段的手册页名字和其所在章节。等同于
man -k program
。 - info command:替代man命令程序手册页,类似于网页,链接可跳转。
builtins
这是shell内部命令,内建于shell自身,例如cd。
- help command:查看builtins命令的帮助文档
shell函数
编写小规模的shell脚本,混合到环境变量中,会在之后详细讨论其编写、配置和使用。
alias别名
自定义自己的命令,建立在其他命令之上。
运行命令的时候可以使用;
进行隔开,使得命令可以依次执行。例如
1 | cd /usr; ls; cd - |
之后使用alias进行重命名。首先需要查看该命令的名字是否被占用。
1 | type test # 发现已经被占用 |
利用其创建alias别名,命令字符串需要紧跟=
。
1 | alias foo='cd /usr; ls; cd -' |
删除别名使用
1 | unalias foo |
I/O 重定向
I/O重定向(I/O代表输入/输出)是一个Linux很有意思的一个特性,可以对Linux的输入和输出进行重定向,来获得想要的结果。
标准输入、标准输出和错误
我们可以发现,在很多命令执行之后会出现一些输出内容,这些内容往往分为两类,一类是程序运行的结果,另一类是程序运行的状态和错误等信息。
与之前提到过的Linux崇尚一切皆文件
同理,这些运行的结果就是将输出的结果传送到一个叫做标准输出(stdout)的文件中,然后再输出出来;而状态和错误信息则被传送标准错误(stderr)文件中;默认情况下,标准输入/输出都连接着屏幕,而不需要保存到文件中。至于标准输入(stdin)则是连接键盘,从中得到输入。
而!此处要提到的I/O重定向,可以允许我们更改输出地点和输入来源
。仔细想想,会发现其中有很多的操作空间。
标准输出重定向
很简单是使用“>
”符号就可以进行标准输出的重定向了。例如直接将ls的内容存储到一个ls-output.txt文件中:
1 | ls -l /usr/bin > ls-output.txt |
可以发现在当前目录新建了一个ls-output.txt文件,可以使用less查看其中的信息。
但是当我们ls一个不存在的目录,就会出现报错的信息:
1 | ls -l /user/bin > ls-output.txt |
此时我们ls -l ls-output.txt
,我们很惊喜的发现,该文件是一个0
字节的文件,说明了两点事情:第一,标准输出的重定向会在每重定向的时候覆盖原本的文件;第二,我们的错误信息并没有重定向到ls-output.txt文件中。
对于覆盖问题,若我们想要在文件最后继续增加标准输入,而不是直接覆盖文件,则可以使用“>>
”符号进行追加:
1 | ls -l /usr/bin >> ls-output.txt |
重复执行两次之后,我们就会发现,该文件大小扩大了一倍,确实是对内容进行了追加。
同样的,若我们需要清空一个文件,则可以简单的使用如下命令即可:
1 | > ls-output.txt |
标准错误重定向
之前提示输入错误的信息,是因为我们此处仅使用了“>
”符号重定向了标准输出,而未重定向标准错误。
但是遗憾的是在Linux中没有特定的符号来重定向标准错误,于是需要借用Linux内定义的文件描述符,每个文件描述符对应一个标准流,前三个文件描述符0、1、2分别对应标准输入、输入和错误。
所以重定向标准错误的时候只需要使用“2>
”即可:
1 | ls -l /user/bin 2> ls-error.txt |
有的时候,我们想要将错误进行隐藏,我们就可以将其重定向到/dev/null
中。
1 | ls -l /user/bin 2> /dev/bin |
使用
ls -l /dev/null
的时候可以发现null的文件属性是c
,指的是串行端口设备。// todo:解释串行端口设备和其他文件属性类型。
当我们想要将标准输入和错误联合输入在同一个文件中,我们有两种方法,一个是旧版的shell中,在标准输出之后,再重定向标准错误(文件描述符2)到标准输出(文件描述符1),注意顺序,否则不起作用:
1 | ls -l /bin/usr > ls-output.txt 2>&1 |
除此以外,现在的bash还提供了新的方法,使用“&>
”符号来联合定义输出和错误重定向。
1 | ls -l /user/bin &> ls-output.txt |
标准输入重定向
在标准输入的重定向之前先提一下需要使用标准输入的地方。
cat [file]:读取一个或多个文件,将其复制到标准输出,直接显示而没有分页,一般用来显示简短的文本。
但是由于其可以读取多个文件的特性,所以就可以利用其来合并文件:
1
cat page*.txt > page.txt
同时!我们需要注意到。这里的file是使用
[]
括起来的,表示可以不读取file文件,那么无输入的时候会读取什么文件就值得去发现了。当我们仅输入cat
后,直接回车!结果什么都没有发生😓,仅有一个闪烁的光标。实际上此时cat是在等待标准输入,并从中来读取数据,尝试键入一些内容,发现就算按下回车也不会结束输入,此时就需要使用
Ctrl和d
来终止输入。为了验证,我们将标准输入再重定向出入到文件中:
1
2cat > cat-context.txt
This is an interesting context.最后使用
Ctrl和d
来终止输入,并cat cat-context.txt
来查看这简短的文本,发现的确将内容输入到了文件中。
最后我们使用“<
”符号就可以进行标准输入重定向:
1 | cat < cat-context.txt |
发现结果与直接cat cat-context.txt
并无差异,但是这里说明了标准输入重定向是可以将标准输入从键盘更改为文件的,更多应用之后再进行讨论。
管道线
管道线具有将命令从一个标准输入读取数据并输送到标准输入的能力。操作符是“|
”
例如标准输出ls和接受标准输入的less:
1 | ls -l /usr/bin | less |
这里我们就可以直接将标准输出内容利用接受标准输入的less显示。
管道线一般是用来对内容进行复杂操作的,可以在管道中增加一些复杂操作,比如增加过滤器,使用sort
对标准输出内容进行一个有序排列,再使用less输出:
1 | ls /bin /usr/bin | sort | less |
想要过滤重复字段,则可以使用uniq
来忽略重复行,想看到重复行的话就使用uniq -d
:
1 | ls /bin /usr/bin | sort | uniq | less |
想统计内容的行数、字数和字节数,则可以使用wc
,增加-l
选项则只显示行数:
1 | ls /bin /usr/bin | sort | uniq | wc -l |
还有一个强大的匹配方法grep
,支持正则表达式进行复杂匹配,并且增加了一些选项,-i
忽略大小写,-v
只显示不匹配的行,例如搜索包含zip字段的内容:
1 | ls /bin /usr/bin | sort | uniq | grep zip |
当输入输出内容太多,而只需要查看前几行或后几行内容的时候,就可以使用head/tail来打印,可以直接使用,也可以在管道线中使用,使用-n
来指定显示的行数。
1 | head -n 5 ls-output.txt |
另外提到 tail有一个选项“
-f
”可以实时浏览文件,来观察日志的变化,例如/var/log/messages
,当读取的文件修改之后,相应内容会立即显示在屏幕上。直到按下Ctri+C
。但是WSL中似乎没有该文件,此处就不进行实验了。
最后再提及一个tee
命令,这是从标准输入中读取内容,并输出到标准输出中,在管道线中可以作为中间段来捕捉在管道线中流动的内容,例如在过滤关键字之前先保存完成的内容到ls.txt中。
1 | ls /usr/bin | tee ls.txt | grep zip |
个人收获
通过这次学习,了解了Linux中命令的区别,之前一直都以为命令都是系统内置的,现在想想一些通过安装的内容确实不是系统内置的,例如之前自己安装的tree
命令,就属于可执行命令。最主要学到的是I/O重定向,这是一个很有趣的内容,可以来觉得自己的标准输入/输出,并且有一个管道可以进行复杂的操作,加上各种有趣的命令,完全就是一个自由度极高的DIY玩具呀!让我们继续快乐学习~