前言##
之前看到一篇介绍 IntelliJ IDEA 配置的文章,它里面用的是 gif 动态图片进行展示,我觉得很不错。所以在我今天以及以后的博文中,我也会尽量使用 gif 动图进行展示。制作 gif 动图很花时间,为了把我的博客打造成精品我也是蛮拼的了。使用动图的优点是演示效果好,缺点是动图体积过大,为了降低图片体积,我只能降低分辨率了。
关于高效使用命令行这个话题,在网上已经是老生常谈了。而且本文也借鉴了 CSDN 极客头条中推荐了的《像黑客一样使用 Linux 命令行》。但是在本文中,也有不少我自己的观点和体会,比如我会提到有些快捷键要熟记,有些则完全不需要记,毕竟我们的记忆力也是有限的,我还会提到一些助记的方法。所以,本文绝对不是照本宣科,值得大家拥有,请大家一定记得点赞。
使用 tmux 复用控制台窗口##
高效使用命令行的首要原则就是要尽量避免非命令行的干扰,什么意思呢?就是说一但开启了一个控制台窗口,就尽量不要再在桌面上切换来切换去了,不要一会儿被别的窗口挡住控制台,一会儿又让别的窗口破坏了控制台的背景,最好是把控制台最大化或全屏,最好连鼠标都不要用。只有这样,才能达到比较高的效率。但是在实际工作中,我们又经常需要同时在多个控制台中进行工作,例如:在一个控制台中运行录制屏幕的命令,在另外一个控制台中工作,或者在一个控制台中工作,在另外一个控制台中阅读文档。如果既想在多个控制台中工作,又不想一大堆窗口挡来挡去、换来换去的话,就可以考虑试试 tmux 了。如下图:
tmux 的功能很多,什么 Session 啊、Detach 啊、Atach 啊什么的我们暂时不用去关心,只用好它的控制台窗口复用功能就行了。tmux 中有 window 和 pane 的概念,tmux 可以创建多个 window,这些 window 是不会互相遮挡的,每次只显示一个 window,其它的 window 会自动隐藏,可以使用快捷键在 window 之间切换。同时,可以把一个 window 切分成多个 pane,这些 pane 同时显示在屏幕上,可以使用快捷键在 pane 之间切换。
tmux 的快捷键很多,要想全面了解 tmux 的最好办法当然是阅读 tmux 的文档了,使用命令 man tmux
就可以了。但是我们只需要记住少数几个重要的快捷键就可以了,如下表:
快捷键 | 功能 |
---|---|
Ctrl+B c | 创建一个 window |
Ctrl+B [n][p] | 切换到下一个窗口或上一个窗口 |
Ctrl+B & | 关闭当前窗口 |
Ctrl+B " | 将当前 window 或 pane 切分成两个 pane,上下排列 |
Ctrl+B % | 将当前 window 或 pane 切分成两个 pane,左右排列 |
Ctrl+B x | 关闭当前 pane |
Ctrl+B [↑][↓][←][→] | 在 pane 之间移动 |
Ctrl+[↑][↓][←][→] | 调整当前 pane 的大小,一次调整一格 |
Alt+[↑][↓][←][→] | 调整当前 pane 的大小,一次调整五格 |
tmux 的快捷键比较特殊,除了调整 pane 大小的快捷键之外,其它的都是先按 Ctrl+B,再按一个字符。先按 Ctrl+B,再按 c,就会创建一个 window,这里 c 就是 create window。先按 Ctrl+B,再按 n 或者 p,就可以在窗口之间切换,它们是 next window 和 previous window 的意思。关闭窗口是先按 Ctrl+B,再按 &,这个只能死记。先按 Ctrl+B,再按 " ,表示上下拆分窗口,可以想象成单引号和双引号在键盘上是上下铺关系。先按 Ctrl+B,再按 % 表示左右拆分窗口,大概是因为百分数都是左右书写的吧。至于在 pane 之间移动和调整 pane 大小的方向键,就不用多说了吧。
在命令行中快速移动光标##
在命令行中输入命令时,经常要在命令行中移动光标。这个很简单嘛,使用左右方向键就可以了,但是有时候我们输入了很长一串命令,却突然要修改这个命令最开头的内容,如果使用向左的方向键一个字符一个字符地把光标移到命令的开头,是否太慢了呢?有时我们需要直接在命令的开头和结尾之间切换,有时又需要能够一个单词一个单词地移动光标,在命令行中,其实这都不是事儿。如下图:
这几种移动方式都是有快捷键的。其实一个字符一个字符地移动光标也有快捷键 Ctrl+B 和 Ctrl+F,但是这两个快捷键我们不需要记,有什么能比左右方向键更方便的呢?我们真正要记的是下面这几个:
快捷键 | 功能 |
---|---|
Ctrl + A | 将光标移动到命令行的开头 |
Ctrl + E | 将光标移动到命令行的结尾 |
Alt + B | 将光标向左移动一个单词 |
Alt + F | 将光标向右移动一个单词 |
这几个快捷键太好记了,A 代表 ahead,E 代表 end,B 代表 back,F 代表 forward。为什么按单词移动光标的快捷键都是以 Alt 开头呢?那是因为按字符移动光标的快捷键把 Ctrl 占用了。但是按字符移动光标的快捷键我们用不到啊,因为我们有左右方向键啊。
在命令行中快速删除文本##
对输入的内容进行修改也是我们经常要干的事情,对命令行进行修改就涉及到先删除一部分内容,再输入新内容。我们碰到的情况是有时候只需要修改个别字符,有时候需要修改个别单词,而有时候,输入了半天的很长的一段命令,我们说不要就全都不要了,整行删除。常用的删除键当然是 BackSpace 和 Delete 啦,不过一次删除一个字符,是否太慢了呢?那么,请熟记以下几个快捷键吧:
快捷键 | 功能 |
---|---|
Ctrl + U | 删除从光标到行首的所有内容,如果光标在行尾,自然就整行都删除了啊 |
Ctrl + K | 删除从光标到行尾的所有内容,如果光标在行首,自然也是整行都删除了啊 |
Ctrl + W | 删除光标前的一个单词 |
Alt + D | 删除光标后的一个单词 |
Ctrl + Y | 将刚删除的内容粘贴到光标处,有时候删错了可以用这个快捷键恢复删除的内容 |
效果请看下图:
这几个快捷键也是蛮好记的,U 代表 undo,K 代表 kill,W 代表 word,D 代表 delete, Y 代表 yank。其中比较奇怪的是 Alt+D 又是以 Alt 开头的,那是因为 Ctrl+D 又被占用了。Ctrl+D 有几个意思,在编辑命令行的时候它代表删除一个字符,当然,这个快捷键其实我们用不到,因为 BackSpace 和 Delete 方便多了。在某些程序从 stdin 读取数据的时候,Ctrl+D 代表 EOF,这个我们偶尔会用到。
快速查看和搜索历史命令##
对于曾经运行过的命令,除非特别短,我们一般不会重复输入,从历史记录中找出来用自然要快得多。我们用得最多的就是 ↑ 和 ↓,特别是不久前才刚刚输入过的命令,使用 ↑ 向上翻几行就找到了,按一下 Enter 就执行,多舒服。但是有时候,明明记得是不久前才用过的命令,但是向上翻了半天也没找到,怎么办?那只好使用 history
命令来查看所有的历史记录了。历史记录又特别长,怎么办?可以使用 history | less
和 history | grep '...'
。但是还有终极大杀招,那就是按 Ctrl+R 从历史记录中进行搜索。按了 Ctrl+R 之后,每输入一个字符,都会和历史记录中进行增量匹配,输入得越多,匹配越精确。当然,有时候含有相同搜索字符串的命令特别多,怎么办?继续按 Ctrl+R,就会继续搜索下一条匹配的历史记录。如下图:
这里,需要记住的命令和快捷键如下表:
命令或快捷键 | 功能 | |
---|---|---|
history | 查看历史记录 | |
history | less | 分页查看历史记录 |
history | grep '...' | 在历史记录中搜索匹配的命令,并显示 |
Ctrl + R | 逆向搜索历史记录,和输入的字符进行增量匹配 | |
Esc | 停止搜索历史记录,并将当前匹配的结果放到当前输入的命令行上 | |
Enter | 停止搜索历史记录,并将当前匹配的结果立即执行 | |
Ctrl + G | 停止搜索历史记录,并放弃当前匹配的结果 | |
Alt + > | 将历史记录中的位置标记移动到历史记录的尾部 |
这里需要注意的是,当我们在历史记录中搜索的时候,是有位置标记的,Ctrl+R 是指从当前位置开始,逆向搜索,R 代表的是 reverse,每搜索一条记录,位置标记都会向历史记录的头部移动,下次搜索又从这里开始继续向头部搜索。所以,我们一定要记住快捷键 Alt+>,它可以把历史记录的位置标记还原。另外需要注意的是停止搜索历史记录的快捷键有三个,如果按 Enter 键,匹配的命令就立即执行了,如果你还想有修改这条命令的机会的话,一定不要按 Enter,而要按 Esc。如果什么都不想要,就按 Ctrl+G 吧,它会还你一个空白的命令行。
快速引用和修饰历史命令##
除了查看和搜索历史记录,我们还可以以更灵活的方式引用历史记录中的命令。常见的简单的例子有 !!
代表引用上一条命令,!$
代表引用上一条命令的最后一个参数,^oldstring^newstring^
代表将上一条命令中的 oldstring 替换成 newstring。这些操作是我们平时使用命令行的时候的一些常用技巧,其实它们的本质,是由 history 库提供的 history expansion 功能。Bash 使用了 history 库,所以也能使用这些功能。其完整的文档可以查看 man history
手册页。知道了 history expansion 的理论,我们还可以做一些更加复杂的操作,如下图:
引用和修饰历史命令的完整格式是这样的:
![!|[?]string|[-]number]:[n|x-y|^|$|*|n*|%]:[h|t|r|e|p|s|g]
可以看到,一个对历史命令的引用被 :
分为了三个部分,第一个部分决定了引用哪一条历史命令;第二部分决定了选取该历史命令中的第几个单词,单词是从0开始编号的,也就是说第0个单词代表命令本身,第1个到最后一个单词代表命令的参数;第三部分决定了对选取的单词如何修饰。下面我列出完整表格:
表格一、引用哪一条历史命令:
操作符 | 功能 |
---|---|
! | 所有对历史命令的引用都以 ! 开始,除了 oldstringnewstring^ 形式的快速替换 |
!n | 引用第 n 条历史命令 |
!-n | 引用倒数第 n 条历史命令 |
!! | 引用上一条命令,等于 !-1 |
!string | 逆向搜索历史记录,第一条以 string 开头的命令 |
!?string[?] | 逆向搜索历史记录,第一条包含 string 的命令 |
oldstringnewstring^ | 对上一条命令进行快速替换,将 oldstring 替换为 newstring |
!# | 引用当前输入的命令 |
表格二、选取哪一个单词:
操作符 | 功能 |
---|---|
0 | 第0个单词,在 shell 中就是命令本身 |
n | 第n个单词 |
第1个单词,使用 ^ 时可以省略前面的冒号 | |
$ | 最后一个单词,使用 $ 是可以省略前面的冒号 |
% | 和 ?string? 匹配的单词,可以省略前面的冒号 |
x-y | 从第 x 个单词到第 y 个单词,-y 代表 0-y |
* | 除第 0 个单词外的所有单词,等于 1-$ |
x* | 从第 x 个单词到最后一个单词,等于 x-$,可以省略前面的冒号 |
x- | 从第 x 个单词到倒数第二个单词 |
表格三、对选取的单词做什么修饰:
操作符 | 功能 |
---|---|
h | 选取路径开头,不要文件名 |
t | 选取路径结尾,只要文件名 |
r | 选取文件名,不要扩展名 |
e | 选取扩展名,不要文件名 |
s/oldstring/newstring/ | 将 oldstring 替换为 newstring |
g | 全局替换,和 s 配合使用 |
p | 只打印修饰后的命令,不执行 |
这几个命令其实挺好记的,h 代表 head,只要路径开头不要文件名,t 代表 tail,只要路径结尾的文件名,r 代表 realname,只要文件名不要扩展名,e 代表 extension,只要扩展名不要文件名,s 代表 substitute,执行替换功能,g 代表 global,全局替换,p 代表 print,只打印不执行。有时候光使用 :p
还不够,我们还可以把这个经过引用修饰后的命令直接在当前命令行上展开而不立即执行,它的快捷键是:
操作符 | 功能 |
---|---|
Ctrl + Alt + E | 在当前命令行上展开历史命令引用,展开后不立即执行,可以修改,按 Enter 后才会执行 |
Alt + ^ | 和上面的功能一样 |
这两个快捷键,记住一个就行。这样,当我们对历史命令的引用修饰完成后,可以先展开来看一看,如果正确再执行。眼见为实嘛,反正我是每次都展开看看才放心。
录制屏幕并转换为 gif 动画图片##
最后,给大家展示我做 gif 动画图片的过程。我用到的软件有 recordmydesktop
、mplayer
和 convert
。使用 recordmydesktop
时需要一个单独的控制台来运行录像功能,录像完成后需要在该控制台中输入 Ctrl+C 终止录像。所以我用到了 tmux 。首先,我启动 tmux,然后运行 recordmydesktop --full-shots --fps 2 --no-sound --no-frame --delay 5 -o ~/图片/record_to_gif.ogv
命令开始录像。由于 recordmydesktop
运行后不会马上退出,录像开始后,这个 window 就被占用了,所以我按 Ctrl+B c 让 tmux 再创建一个 window,然后在这个 window 中做的任何操作都会被录制下来。被录制的操作完成后,按 Ctrl+B n 切换到 recordmydesktop
命令运行的窗口,按 Ctrl+C 终止录像。然后,使用 mplayer -ao null record_to_gif.ogv -vo jpeg:outdir=./record_to_gif
将录制的视频提取为图片。当然,这时的图片比较多,为了缩减最后制作成的 gif 文件的大小,我们可以删掉其中无关紧要的帧,只留下关键帧。最后使用命令 convert -delay 100 record_to_gif/* record_to_gif.gif
生成 gif 动画。整个过程如下图:
最后生成的 gif 图片一般都比较大,往往超过 20M,如果时间长一点,超过 60M 也是常事儿。而制作成 gif 之前每一帧图片也就 200k 左右而已。我想可能是因为 gif 没有像 jpeg 或 png 这么好的压缩算法吧。gif 对付向量图效果很不错,对付照片和我这样的截图,压缩就有点力不从心了。博客园允许上传的图片每张不能超过 10M,所以,为了减小 gif 文件的体积,我只有用 convert -resize 1024x576 record_to_gif.gif record_to_gif_small.gif
命令将图片变小后再上传了。
总结##
使用 Linux 命令行的技巧还有很多,我这里不可能全部讲到。学习 Linux 命令行的最好办法当然还是使用 man bash
查看 Bash 的文档。但是我这里讲的内容已经可以显著提高使用命令行的效率了,至少这两天下来,我觉得我自己有了质的飞跃。另外,在博客中使用 gif 动态图片做示例,我觉得也是我写博客以来一个质的飞跃。希望大家喜欢。