像黑客一樣使用 Linux 命令行


前言##

之前在博客園看到一篇介紹 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 | lesshistory | 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個到最后一個單詞代表命令的參數;第三部分決定了對選取的單詞如何修飾。下面我列出完整表格:

表格一、引用哪一條歷史命令:

操作符 功能
! 所有對歷史命令的引用都以 ! 開始,除了 ^oldstring^newstring^ 形式的快速替換
!n 引用第 n 條歷史命令
!-n 引用倒數第 n 條歷史命令
!! 引用上一條命令,等於 !-1
!string 逆向搜索歷史記錄,第一條以 string 開頭的命令
!?string[?] 逆向搜索歷史記錄,第一條包含 string 的命令
^oldstring^newstring^ 對上一條命令進行快速替換,將 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 動畫圖片的過程。我用到的軟件有 recordmydesktopmplayerconvert。使用 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 動態圖片做示例,我覺得也是我寫博客以來一個質的飛躍。希望大家喜歡。

(京山游俠於2016-08-11發布於博客園,轉載請注明出處。)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM