# 生產力工具:shell 與 Bash 腳本
作者:吳甜甜?
個人博客網站: wutiantian.github.io?
注意:本文只是我個人總結的學習筆記,不適合0基礎人士觀看。
----
參考內容:
王頂老師 linux bash 視頻教程
http://billie66.github.io/TLCL/book
C語言編程網:? http://c.biancheng.net/shell/
推薦書籍:《UNIX環境編程》,有內容,有遠離,課后習題也很棒。
---
目錄
<!-- TOC -->
- [生產力工具:shell 與 Bash 腳本](#生產力工具shell-與-bash-腳本)
- [我為什么學 shell](#我為什么學-shell)
? ? - [什么是 shell 與 BASH](#什么是-shell-與-bash)
? ? - [學 shell 與 BASH 立竿見影的好處](#學-shell-與-bash-立竿見影的好處)
- [三步編寫執行一個 Shell 腳本](#三步編寫執行一個-shell-腳本)
- [命令](#命令)
? ? - [命令提示符與命令的概念簡述](#命令提示符與命令的概念簡述)
? ? - [命令的詳細](#命令的詳細)
- [linux系統基礎操作](#linux系統基礎操作)
? ? - [linux思想:一切皆文件](#linux思想一切皆文件)
? ? - [探索操作系統狀態](#探索操作系統狀態)
? ? - [linux文件系統跳轉](#linux文件系統跳轉)
? ? - [操作文件和目錄](#操作文件和目錄)
? ? - [文本處理](#文本處理)
? ? - [停止](#停止)
? ? - [權限](#權限)
? ? - [軟件安裝管理](#軟件安裝管理)
? ? - [編譯程序make](#編譯程序make)
- [shell眼中看世界——“展開”](#shell眼中看世界展開)
? ? - [字符展開](#字符展開)
? ? - [路徑名展開](#路徑名展開)
? ? - [波浪線展開](#波浪線展開)
? ? - [算術表達式展開](#算術表達式展開)
? ? - [花括號展開](#花括號展開)
? ? - [參數展開](#參數展開)
? ? - [命令(展開)替換](#命令展開替換)
? ? - [引用-控制展開](#引用-控制展開)
? ? - [引用-雙引號-限制部分展開](#引用-雙引號-限制部分展開)
? ? - [引用-單引號-禁止展開](#引用-單引號-禁止展開)
? ? - [轉義字符](#轉義字符)
- [IO 重定向](#io-重定向)
? ? - [IO](#io)
? ? - [重定向](#重定向)
? ? - [管道操作符\|提取數據](#管道操作符\提取數據)
- [正則表達式](#正則表達式)
? ? - [用“元字符”實現復雜匹配](#用元字符實現復雜匹配)
? ? - [元字符和原義字符](#元字符和原義字符)
? ? - [grep](#grep)
- [專項專題(選看)](#專項專題選看)
? ? - [顯示與查找文件](#顯示與查找文件)
? ? - [歸檔 tar、解壓、批量](#歸檔-tar解壓批量)
? ? - [內存與進程的性能](#內存與進程的性能)
? ? - [存儲媒介-設備掛載](#存儲媒介-設備掛載)
? ? - [網絡](#網絡)
- [定制 shell](#定制-shell)
? ? - [shell環境](#shell環境)
? ? - [定制 shell 提示符$PS1](#定制-shell-提示符ps1)
? ? - [別名alias-創建你自己的命令](#別名alias-創建你自己的命令)
- [寫腳本](#寫腳本)
? ? - [注釋第一行](#注釋第一行)
? ? - [變量](#變量)
? ? - [使用變量](#使用變量)
? ? - [聲明數組](#聲明數組)
? ? - [表達式](#表達式)
? ? - [數學運算](#數學運算)
? ? - [流程控制-if](#流程控制-if)
? ? - [流程控制-循環](#流程控制-循環)
? ? - [語句](#語句)
? ? - [腳本習題](#腳本習題)
- [附錄:如何查看 man 幫助手冊](#附錄如何查看-man-幫助手冊)
- [附錄:學習方法](#附錄學習方法)
- [附錄:鳴謝](#附錄鳴謝)
<!-- /TOC -->
# 我為什么學 shell
我首先接觸到 shell 是在深圳的一家fpga的方案公司參觀交流時,看到工程師對fpga進行編程時,敲幾個字符就插入了代碼塊,感覺很快,是生產力的決勝武器。工程師告訴我,每個 fpga 公司都有自己的核心技術專利,編寫好的私有庫就是通過幾個字符的腳本插入到程序中,每家都不同,模塊不對外公開。
**我意識到,成為具有核心價值的工程師必須掌握這項技能!**
我本科時學的是電子信息工程,對軟件的態度并沒有什么都要會的意識,只是用到再學。但對于 shell ,它并不能迫在眉睫能解決什么必須處理的問題,卻成為人與人差距的重要一環之一。
寫本內容時,是應用于圖像機器學習中遇到實際問題寫的個人筆記。當我準備用手頭的《Linux程序設計》書時,很失望,看著塊頭挺大。內容可看的不多。網上的博客大多數內容比較淺,實戰性不強。所以我自己寫給自己復習。
*嵌入式的shell是精簡過的,語法略有不同,這點要注意。比如說數組,部分命令的輸出和PC尚的存在一定差異。*
## 什么是 shell 與 BASH
- shell:
? ? 一說到命令行,我們真正指的是 shell。
? ? **shell 就是一個程序,它接受從鍵盤輸入的命令, 然后把命令傳遞給操作系統去執行。**
- BASH?
? ? “bash” 是 “Bourne Again SHell” 的首字母縮寫。
? ? bash 是由 Steve Bourne 的人寫成 **shell 程序的增強版**
因為基于“命令行”界面,而不是“圖形”界面,所以 shell 與 bash 的適應性更強,能應用在**多種系統**中,是“**通殺**”的技能。
## 學 shell 與 BASH 立竿見影的好處
|常用功能例舉|功能簡述|優勢|功能|
|---|---|---|---|
|1|自動運行命令行|自動執行多組操作|添加一條命令行,每次輸入幾個字符(打開bash)時都會自動運行|
|2|alias別名|簡化單組操作字符數|
# 三步編寫執行一個 Shell 腳本
|步驟|內容|詳細|
|:---|:---:|:---|
|1|**編寫一個腳本。**|shell 腳本就是普通的文本文件。所以我們需要一個文本編輯器來書寫它們。最好的文本 編輯器都會支持語法高亮,這樣我們就能夠看到一個腳本關鍵字的彩色編碼視圖。語法高亮會幫助我們查看某種常見 錯誤。為了編寫腳本文件,vim,gedit,kate,和許多其它編輯器都可以。|
|2|使腳本文件**可執行**。|系統會相當挑剔不允許任何舊的文本文件被看作是一個程序,并且有充分的理由! 所以我們需要設置腳本文件的權限來允許其可執行。|
|3|把腳本放置到 shell 能夠找到**當前目錄下**。|當沒有指定可執行文件明確的路徑名時,shell 會**自動地搜索某些目錄**, 來查找此可執行文件。為了最大程度的方便,我們會把腳本放到這些目錄當中。|
# 命令
## 命令提示符與命令的概念簡述
- 命令提示符:說明 **shell已經準備好輸入了**。
>[當前用戶登錄名@linux主機名 當前路徑]$
例如: [Teenie@wutiantian.github.io ~]$?
表示:當前用戶Teenie在主機名為wutiantian.github.io的當前路徑為家目錄
注意,后續的“定制 shell 環境”章節 有具體更改為自己心中環境的設置過程。
- 命令行語法
>command -options arguments
>命令 一個或多個選項 一個或多個參數對象
以“空格”分隔,不管幾個空格都算一個空格。
例如:? ls -l? /usr
- 如何選擇命令行發揮更大優勢
|界面|優勢|
|---|---|
|圖形|簡單的任務更簡單|
|命令行|復雜的任務成為可能|
## 命令的詳細
選項 options 分為 短選項和長選項,**功能效果一樣**。
|options|舉例|優勢|描述|
|---|---|---|:---|
|short|-a|效率高|格式為'-'**單橫杠**。<br>短選項可**合并**。若'-'后不止一個字母則為合并選項。<br>例如:-a與-l合并為-al全部列出功能|
|long|--all|更直觀|格式為'--'**雙橫杠**。<br>長選項沒有合并說法。|
|命令|四種形式||
|---|:---:|:---:|
|execute binary<br>可執行二進制|就像我們所看到的位于目錄/usr/bin 中的文件一樣|用諸如 C 和 C++語言寫成的**程序編譯**的**二進制文件**, 也可以是由諸如shell,perl,python,ruby等等**腳本語言**寫成的程序 |
|buildin bash<br>內嵌bash命令|bash 支持若干命令,內部叫做 shell 內部命令 (builtins)|例如,cd 命令,就是一個 shell 內部命令。|
|shell function 函數|這些是小規模的 shell 腳本|它們混合到環境變量中。|?
|alias 命令別名|定義自己的命令|建立在其它命令之上|
|命令|檢測命令的四種形式歸屬|舉例|舉例|
|---|---|---|---|
|type|Indicate how a command name is interpreted<br>說明怎樣解釋一個命令名|type command<br>**四種命令形式的哪一種**|#type type <br> type is a shell builtin <br> #type ls<br>ls is aliased to `ls --color=auto'<br>#type cp<br>cp is /bin/cp|
|which|To determine the exact location of a given executable, the which command is used:<br>顯示可執行程序的**位置**|which command<br>一個操作系統中,不只安裝了可執行程序的一個版本,為了確定所給定的執行程序的準確位置,使用 which 命令<br>**這個命令只對可執行程序有效**|#which cp<br>/bin/cp<br>#which cd<br>使用 shell 內建命令時,得不到回應。|
|help|得到**shell 內建命令的(簡要)幫助文檔**|command --help<br>help command<br>幫助文件可能是**中文**也可能是**英文**|help cd<br>cd --help|
|man|**詳細**用戶幫助|man command|man ls \| less|
|apropos|基于某個關鍵字的**搜索**匹配項,很粗糙但有時很有用|apropos command<br>等價于man -k|
|whatis|The whatis program displays the name and a one line description of a man page matching a specified<br>顯示**匹配特定關鍵字**的**手冊頁**的名字和**一行命令說明**|whatis command|whatis ls<br>ls(1)- list directory contents|
|info|info 內容可通過 info 閱讀器 程序讀取。info 頁是超級鏈接形式的,和**網頁很相似,退出就消失了痕跡**。<br>info 文件包含超級鏈接,它可以讓你從一個結點跳到另一個結點。一個**超鏈接**可通過 它開頭的**星號來辨別**出來,把光標放在它上面并**按下 enter 鍵,就可以激活它**。|info command|info ls|
>help cd
長說明
```
cd: cd [-L|[-P [-e]] [-@]] [dir]
? ? Change the shell working directory.
? ? Change the current directory to DIR.? The default DIR is the value of the
? ? HOME shell variable.
? ? The variable CDPATH defines the search path for the directory containing
? ? DIR.? Alternative directory names in CDPATH are separated by a colon (:).
? ? A null directory name is the same as the current directory.? If DIR begins
? ? with a slash (/), then CDPATH is not used.
? ? If the directory is not found, and the shell option `cdable_vars' is set,
? ? the word is assumed to be? a variable name.? If that variable has a value,
? ? its value is used for DIR.
? ? Options:
? ? ? ? -L??force symbolic links to be followed: resolve symbolic links in
? ? ????DIR after processing instances of `..'
? ? ? ? -P??use the physical directory structure without following symbolic
? ? ????links: resolve symbolic links in DIR before processing instances
? ? ????of `..'
? ? ? ? -e??if the -P option is supplied, and the current working directory
? ? ????cannot be determined successfully, exit with a non-zero status
? ? ? ? -@? on systems that support it, present a file with extended attributes
? ? ? ? ? ? as a directory containing the file attributes
? ? The default is to follow symbolic links, as if `-L' were specified.
? ? `..' is processed by removing the immediately previous pathname component
? ? back to a slash or the beginning of DIR.
? ? Exit Status:
? ? Returns 0 if the directory is changed, and if $PWD is set successfully when
? ? -P is used; non-zero otherwise.
```
>cd --help
短說明
```
bash: cd: --: invalid option
cd: usage: cd [-L|[-P [-e]] [-@]] [dir]
```
>apropos ls
匹配關鍵字
等價于man -k ls
```
SSL (3ssl)? ? ? ? ? - OpenSSL SSL/TLS library
_llseek (2)? ? ? ? ? - reposition read/write file offset
aconnect (1)? ? ? ? - ALSA sequencer connection manager
add-shell (8)? ? ? ? - add shells to the list of valid login shells
afInitChannels (3)? - initialize audio data format for a track in an audio f...
afOpenFile (3)? ? ? - open an audio file and create a file handle structure ...
afs_syscall (2)? ? ? - unimplemented system calls
afSetVirtualChannels (3) - set the virtual data format for a track in an audi...
afSetVirtualSampleFormat (3) - set the virtual data format for a track in an ...
alsabat (1)? ? ? ? ? - command-line sound tester for ALSA sound card driver
alsactl (1)? ? ? ? ? - advanced controls for ALSA soundcard driver
alsactl_init (7)? ? - alsa control management - initialization
alsaloop (1)? ? ? ? - command-line PCM loopback
alsamixer (1)? ? ? ? - soundcard mixer for ALSA soundcard driver, with ncurse...
amidi (1)? ? ? ? ? ? - read from and write to ALSA RawMIDI ports
amixer (1)? ? ? ? ? - command-line mixer for ALSA soundcard driver
aplay (1)? ? ? ? ? ? - command-line sound recorder and player for ALSA soundc...
...
```
# linux系統基礎操作
## linux思想:一切皆文件
|顏色屬性|白|藍|淺藍|綠|紅|紅色閃爍|黃|灰|
|---|---|---|---|---|---|---|---|---|---|
|文件類型|普通文件|目錄|鏈接文件|可執行文件|壓縮文件|鏈接有問題文件|設備文件|其他文件|
```
解析例如:
檔案類型權限 連節數 檔案擁有者? 檔案所屬群組? 文件大小? 檔案最后被修改時間? 檔名
-rw-r--r--? 1? ? ? Teenie? ? ? Teenie? ? 3803? ? 6月? 24 21:43? ? .bashrc
```
文件類型標記方法:
|首位|類型|舉例|文件舉例|
|---|---|---|---|
|-|普通文件|文本文件、二進制文件|a.c , 1.txt? , a.out? , test1.sh ,bbbb.txt-hard看不出類型的文本硬鏈接|
|d|文件夾||cache/|
|l|符號鏈接文件|后面會用->打印出它指向的文件|ln -s src.c linker.c<br>linker.c就是src.c的一個符號鏈接文件<br>lrwxrwxrwx 1 root root 3 .... linker.c -> src.c|
|s|socket文件||
|p|管道文件|||
|文件權限|含義|
|---|:---:|
|r|可讀|
|w|可寫|
|x|可執行|
|-|空權限,沒有權限<br>不可執行Permission denied|
|文件目錄結構|內容|
|---|---|
|bin|存儲二進制**可執行命令文件**(綠色)|
|root|**root超級用戶**,即根用戶的主目錄|
|home|**普通用戶**的默認家目錄,每個普通用戶擁有一個以用戶名命名的文件夾|
|mnt|**可移除設備掛載點**。例如:光驅。共享文件夾目錄/mnt/ghfs/|
|media|可移除設備|
|etc|**配置文件和目錄**<br>/etc/crontab寫腳本或定時運行一些任務,有定時設置。<br>/etc/fstab系統掛載的磁盤ID<br>**/etc/passwd所有用戶的賬號密碼**|
|proc|操作系統正在運行進程的文件列表。可用“file 文件名”去查看用途|
|lib|存儲各種程序所需要的**共享庫文件**|
|opt|optional可選的,第三方軟件可安裝至此|
|boot|存放ubuntu內核和**系統啟動文件**<br>/boot/grub/grub.conf or menu.lst,被用來配置啟動加載程序。<br>/boot/vmlinuz,Linux 內核|
|var|用于存放很多不斷變化的文件,例如日志文件等。<br>/var/log 目錄包含日志文件、各種系統活動的記錄。<br>這些文件非常重要,并且 應該時時監測它們。|
|tmp|存儲系統和用戶的臨時信息|
|user|包括與系統用戶直接有關的文件和目錄|
|sbin|系統命令的存儲位置|
- linux文件存儲
至少包括兩部分,(1)文件數據本身(2)文件原數據?
原數據包括:文件屬性(創建時間、修改時間、所有者、權限、文件名)。?
這些原數據鏈接到了數據塊本身,所以**本身就是一個硬鏈接**。?
當硬鏈接數量比1少時,文件就被刪除了。
|類型|硬鏈接|軟鏈接|
|------|---|---|
|局限性|**不能指向到目錄**<br>有 ln file link無ln directory link<br>文件和鏈接文件不能位于不同設備|符號鏈接:鏈接、原文件。刪除鏈接,原文件不受影響。<br>刪除原文件則鏈接文件指向空,野指針,在操作系統有紅色顯示|
|外觀|硬鏈接在ls命令下是看不出區別的。|符號鏈接課看出符號指向<br>sbin->usr/sbin|
## 探索操作系統狀態
>date
顯示系統當前時間和日期
This command displays the current time and date.
```
2019年 06月 30日 星期日 18:21:15 CST
```
>cal
顯示當前月份的日歷
A related command is cal which, by default, displays a **calendar** of the current month.
```
? ? ? 六月 2019? ? ? ?
日 一 二 三 四 五 六?
? ? ? ? ? ? ? ? ? 1?
2? 3? 4? 5? 6? 7? 8?
9 10 11 12 13 14 15?
16 17 18 19 20 21 22?
23 24 25 26 27 28 29?
30? ? ? ? ? ? ?
```
>exit
結束終端會話
We can end a terminal session by either closing the terminal emulator window, or by entering the exit command at the shell prompt:
>file filename
確定文件類型
>file ~/.bashrc
/home/Teenie/.bashrc: ASCII text
## linux文件系統跳轉
|命令|全英文|用法|
|---|:---:|:---:|
|pwd|Print name of current working directory<br>打印出當前工作的絕對路徑|pwd **我是誰?我在哪?**|
|ls|List directory contents<br>列出目錄內容|ls<br>什么都不跟,查看當前目錄資料<br>ls /dev<br>查看指定路徑下資料<br>|
|cd|Change directory<br>更改目錄|cd <br>什么都不跟,回到家目錄<br>cd ~username<br>回到某用戶家目錄<br>cd -<br>切換到前一個操作目錄<br>cd Teenie/<br>切換到指定路徑下目錄|
>[Teenie@wutiantian.github.io ~]$ pwd
/home/Teenie
普通用戶根目錄的工作目錄名:在home目錄下的該用戶名地址下。
>ls
|常用選項|長選項|作用|舉例|
|---|---|---|---|
|-a|--all|列出目錄下的所有內容,包括隱藏的|
|-d|--directory|該目錄本身的信息(單)行|ls -ld /usr<br>drwxr-xr-x. 13 root root 155 6月 30 03:28 /usr
|-F|--classify|文件或者目錄名字后加一個字符的分類標識|/目錄,例如opt/; @鏈接,例如 bin@|
|-h|--human-readable|可讀模式|將**容量**4096轉為4.0k,<br>避免太大數字不能直觀看出多大|
|-l|long長格式輸出||
|-r|--reverse|反序,字母**降序排列文件夾**|
|-t|--time|按修改日期排序|
>cd Teenie/
切換到當前路徑下的Teenie文件夾目錄路徑下
在幾乎所有的情況下,你**可以省略”./”。它是隱含的**。
To change your working directory (where we are standing in our tree-shaped maze) we use the cd command. To do this, type cd followed by the pathname of the desired working directory. A pathname is the route we take along the branches of the tree to get to the directory we want. Pathnames can be specified in one of two different ways; as absolute pathnames or as relative pathnames. Let’s deal with absolute pathnames first.
|路徑的兩種方式|特征|
|---|---|
|相對路徑|用**一對特殊符號**來表示相對位置:符號 “.” 指的是工作目錄,”..” 指的是工作目錄的父目錄|
|絕對路徑|**根目錄開頭**的“/”開始,直到它的目的地|
>cd ..
切換到上一級目錄
## 操作文件和目錄
|命令|含義|示例|
|---|---|---|
|mkdir|make directory|mkdir dir1<br>mkdir dir1 dir2 dir3|
|cp|copy|cp item1 item2 把單個文件item1復制成item2<br>cp item... directory 復制多個item文件/文件夾到directory文件夾|
|mv|move|移動、重命名文件|
|rm|remove|-i交互咨詢;<br>-r遞歸;<br>-f,--force ;<br>-v,--verbose,explain what is being done。<br>rm file1 <br>????默默地刪除文件<br>rm -i file1 <br>?除了在刪除文件之前,提示用戶確認信息之外,和上面的命令作用一樣。<br>rm -r file1 dir1 <br>???刪除文件 file1, 目錄 dir1,及 dir1 中的內容。<br>rm -rf file1 dir1 <br>??除了如果文件 file1,或目錄 dir1 不存在的話,rm 仍會繼續執行。||
|ln|link|ln file link創建硬鏈接;<br>ln bbb.txt bbb.txt-hard<br>ln -s item link創建符號鏈接<br>ln -s fun fun-sym|
附:**item 表示文件或目錄**
>cp /etc/passwd .
將用戶賬戶密碼拷貝至當前目錄
>cp -v /etc/passwd .
"/etc/passwd"->"./passwd"
顯示操作過程
>cp -i /etc/passwd .
cp:是否覆蓋"./passwd"?
>cp a passwd dir1
將a與passwd文件,復制到dir1文件夾中
|cp短選項|長選項|意義|
|---|:---:|:---:|
|-a|--archive|**復制文件和目錄,以及它們的屬性**,包括所有權和權限。 通常,副本具有用戶所操作文件的默認屬性。|
|-i|--interactive|在**重寫已存在文件之前,提示用戶確認**。如果這個選項不指定, cp 命令會默認重寫文件。|
|-r|--recursive|**遞歸地復制目錄及目錄中的內容**。當復制目錄時, 需要這個選項(或者-a 選項)。|
|-u|--update|當把文件從一個目錄復制到另一個目錄時,**僅復制**目標目錄中不存在的文件,或者是文件內容新于目標目錄中已經存在的文件。|
|-v|--verbose|顯示翔實的**命令操作信息**|
|mv短選項|長選項| ????意義|
|---|---|---|
|-i| --interactive |????在重寫一個已經存在的文件之前,**提示用戶確認信息**。 如果不指定這個選項,mv 命令會默認重寫文件內容。|
|-u| --update| ?當把文件從一個目錄移動另一個目錄時,只是移動不存在的文件, 或者文件內容新于目標目錄相對應文件的內容。|
|-v| --verbose |????當操作 mv 命令時,顯示翔實的操作信息。|
## 文本處理
文本處理用處:文檔、網頁、電子郵件、打印輸出、程序源代碼
- 排序
|排序命令|功能|
|---|---|
|cat|連接文件并且打印到標準輸出|
|sort|給文本行排序,結果發送到標準輸出|
|uniq|報告或者省略重復行|
|cat選項|功能|
|---|---|
|-A|打印文本文檔中的非打印字符|
|-n|number增加行號在文本中|
|-s|合并多余空行。3個連續空行變為1個|
|非打印字符|名稱|顯示效果|
|---|---|---|
|enter|回車鍵|$|
|tab|制表鍵|^I|
|space|空格||
>cat -A hello.c
打印 hello.c 文本文檔中的非打印字符,讓人更明了程序排版
```
#include<stdio.h>$
int main(void)$
{$
? ? printf("hello world");$
? ? return 0;$
} $
```
sort 程序對標準輸入的內容,或命令行中指定的一個或多個文件進行排序,然后把排序 結果發送到標準輸出。
使用與 cat 命令相同的技巧,我們能夠演示如何用 sort 程序來處理標準輸入
```
sort >foo.txt
c
a
b
Ctrl-d 組合鍵來表示文件的結尾
cat foo.txt
a
b
c
看到文本行有序地顯示
```
sort 程序能接受命令行中的多個文件作為參數,所以有可能把多個文件合并成一個有序的文件。
例如, 如果我們有三個文本文件,想要把它們合并為一個有序的文件。
>sort file1.txt file2.txt file3.txt > final_sorted_list.txt
|sort 程序選項|長選項 |????功能|
|---|---|---|
|-b|--ignore-leading-blanks|默認情況下,對整行進行排序,從每行的第一個字符開始。這個選項導致 sort 程序**忽略** 每行開頭的**空格**,從第一個非空白字符開始排序。|
|-f|--ignore-case |?讓排序不區分大小寫。|
|-n |???--numeric-sort |????基于字符串的數值來排序。使用此選項允許根據數字值執行排序,而不是字母值。
|-r |???--reverse |?按相反順序排序。結果按照**降序排列**,而不是升序。
|-k |???--key=field1[,field2]<br>偏量| ???根據**字段排序**|
|-m |???--merge |???把每個參數看作是一個預先排好序的文件。把多個文件合并成一個排好序的文件,而沒有執行額外的排序。
|-o |???--output=file |?把排好序的輸出結果發送到文件,而不是標準輸出。
|-t| ???--field-separator=char| ????定義域**分隔字符**。默認情況下,域由空格或制表符分隔。
>du -s /usr/share/* |sort -nr |head
查看磁盤中目錄,哪個文件夾占用磁盤空間大,數字逆序排列前十個
```
245984??/usr/share/fonts
122532??/usr/share/icons
114424??/usr/share/doc
89328???/usr/share/help
82640???/usr/share/libreoffice
60556???/usr/share/pyzy
55588???/usr/share/app-install
42228???/usr/share/mythes
41496???/usr/share/fcitx-sogoupinyin
39692???/usr/share/man
```
|uniq 選項|功能|
|---|---|
|-c|輸出所有的重復行,并且每行開頭顯示重復的次數。|
|-d|只輸出重復行,而不是特有的文本行。|
|-f n|忽略每行開頭的 n 個字段,字段之間由空格分隔,正如 sort 程序中的空格分隔符;然而, 不同于 sort 程序,uniq 沒有選項來設置備用的字段分隔符。|
|-i|在比較文本行的時候忽略大小寫。|
|-s n|跳過(忽略)每行開頭的 n 個字符。|
|-u|只輸出獨有的文本行。這是默認的。|
- 切片
|命令|功能|例子|
|---|---|---|
|cut|裁剪,從文件里取東西|cut -f 2,2 linux-by-date.txt >linux-vernums.txt|
|paste|**合并**文件文本行<br>通過讀取多個文件,然后把每個文件中的字段整合成單個文本流,輸入到標準輸出。|paste linux-dates.txt linux-names.txt >linux-key-names.txt|
|join|往文件里加東西|join linux-key-names.txt linux-key-vernums.txt|
- 比較
|查看差異命令|功能|例子|
|---|---|---|
|comm|逐行比較兩個有序的文件<br>compare|
|diff|逐行比較文件或目錄<br>different<br>**如何把文件1編程文件2**|
|patch|把更改應用到原始文檔中去|diff -Naur old_file new_file >patchfile.txt<br>patch < patchfile.txt|
<br>
|diff三種模式|模式內容|示例|
|---|---|---|
|normal|描述要求更改的位置和類型|
|context|上下文模式。信息有冗余|-刪除行<br>+增加行<br>!更改行|
|unin|統一模式|空格:兩個文件都包含這一行<br>-:在第一個文件中刪除這一行<br>+:添加這一行到第一個文件中|
```
cat file1.txt
a
b
c
d
cat file2.txt
b
c
d
e
comm file1.txt file2.txt
a
? ? ? ? ? ? b
? ? ? ? ? ? c
? ? ? ? ? ? d
? ? e
1特? 2特? 共有
comm -12 file1.txt file2.txt
b
c
d
隱藏12列
diff file1.txt file2.txt? ? ? ? ?
1d0? ? 如何把file1改成file2.txt?
< a? ? 刪除d第一行的a
4a4? ? 把第2個文件的第4行
> e? ? 加上e
diff -c file1.txt file2.txt
context模式
*** file1.txt
--- file2.txt
*************
*** 1,4 *****
-a
b
c
d
--- 1,4 -----
b
c
d
+e
diff -u file1.txt file2.txt
unin 統一模式
---file1.txt
+++file2.txt
@@-1,4,+1,4@@
-a
b
c
d
+e
```
- 運行時編輯
The tr program is used to transliterate characters.
tr 程序被用來更改字符。我們可以把它看作是一種基于字符的查找和替換操作。
|命令|功能|例子|
|---|---|---|
|tr|search/replace查找與替換|tr char_set1 char_set2<br>在第一個字符集里查找,替換成第2個字符集內容|
|charset三種模式|內容|
|---|---|
|list枚舉|abcdefghijklmnop|
|field域|a-z or A-Z or 0-9|
|POSIX|[:lower:][:upper:]
## 停止
|停止的快捷鍵|功能|例子|
|---|---|---|
|ctrl+z|將任務中止(暫停的意思),但是此任務并沒有結束。<br>他仍然在進程中他只是**維持掛起的狀態**,<br>用戶可以使用fg/bg操作繼續前臺或后臺的任務,<br>fg命令重新啟動前臺被中斷的任務,<br>bg命令把被中斷的任務放在后臺執行.|當你vi一個文件是,如果需要用shell執行別的操作,<br>但是你又不打算關閉vi,<br>因為你得存盤退出,<br>你可以簡單的按下ctrl+z,<br>shell會將vi進程掛起,<br>當你結束了那個shell操作之后,<br>你可以用fg命令繼續vi你的文件。|
|ctrl+c|強制中斷程序的執行,**進程**已經**終止**。|
|ctrl+d| 不是發送信號,而是表示一個特殊的二進制值,表示 EOF。<br>在shell中,**ctrl-d表示退出當前shell**|
## 權限
Linux 系統有**多用戶**性能。
為了使多用戶特性付諸實踐,那么必須發明一種方法來阻止用戶彼此之間受到影響。
畢竟,**一個用戶的行為不能導致計算機崩潰,也不能亂動屬于另一個用戶的文件。**
|命令|詳解|示例|
|---|---|---|---|
|id |Display user identity<br>顯示**當前用戶身份**號|#id|
|chmod|Change a file’s mode<br>更改**已經存在的文件模式**|支持兩種不同的方法來改變文件模式:八進制數字表示法或 符號表示法。|
|umask|Set the default file permissions<br>設置默認的**新創建文件權限**|umask 0002<br>默認權限減2|
|chown|Change a file’s owner<br>更改文件**所有者**|
|chgrp|Change a file’s group ownership<br>更改文件**組所有權**|
|su|Run a shell as another user<br>以另一個用戶的**身份**來運行 shell|
|sudo|Execute a command as another user<br>以另一個用戶的**身份**來執行命令|
|passwd|Change a user’s password<br>更改**用戶密碼**|passwd [user]
在 Unix 術語中,每個人 是指整個世界。可以**用 id 命令,來找到關于你自己身份的信息**
>id
uid=1000(teenie) gid=1000(teenie) groups=1000(teenie),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),113(lpadmin),128(sambashare)
|id組的字符|含義|||||
|---|---|---|---|---|---|
|u|g|o|a|||
|owner<br>user|group|other|all=user+group+other|||
uid 從1000開始變號
|屬性|文件(直觀)|目錄(不直觀,需記憶)|
|---|---|---|
|r|允許打開并讀取文件內容|允許列出目錄中的內容,<br>前提是目錄必須設置了可執行屬性(x)|
|w|允許寫入文件內容或截斷文件。<br>但不允許對文件進行重命名或刪除,<br>重命名或刪除是由目錄的屬性決定的|允許在目錄下新建、刪除或重命名文件,<br>前提是目錄必須設置了可執行屬性(x)|
|x|允許將文件作為程序來執行,使用腳本語言編寫的程序必須設置為可讀才能被執行|允許進入目錄,例如:cd directory|
權限的基礎組合值
|Octal|Binary|File Mode|
|---|---|---|---|
|1|001|--x|execute|
|2|010|-w-|write|
|4|100|r--|read|
八進制有8種組合,對以上三種進行組合相加賦值即可。
- 對于腳本文件,有兩個常見的權限設置
|腳本權限值|功能|
|---|---|
|755|每個人都能執行|
|700|只有文件所有者能夠執行|
注意:為了能夠**執行腳本文件**,腳本必須是**可讀的**。
>chmod
```
chmod gu=rw foo.txt
組權限賦值
chmod o-x foo.txt
減去other組的x可執行功能
chmod 755 foo.txt
把文件的權限設為755
```
## 軟件安裝管理
**軟件包管理工具:系統中,一種安裝和維護軟件的方法**
如果我們花些時間在 Linux 社區里,我們會看到很多像Linux發行版中哪一個是“最佳”之類的觀點。 這些討論通常非常可笑,集中在一些像桌面背景的漂亮程度(一些人不使用 Ubuntu, 只是因為 Ubuntu 默認主題顏色是棕色的!)和其它的瑣碎東西上。
Linux 發行版本質量最重要的決定因素是軟件包管理系統和其支持社區的持久性。隨著我們 花更多的時間在 Linux 上,我們會發現它的變化是非常快的。大多數一線 Linux 發行版每隔六個月發布一個新版本,并且許多獨立的程序每天都會更新。為了能和這些 如暴風雪一般多的軟件保持聯系,我們需要一些好工具來進行軟件包管理。
**選擇 linux 發行版的重要指標:軟件包管理**
|該發行版是否有|
|---|
|1.好用的軟件包管理系統|
|2.豐富的軟件包使用|
|3.持久的社區維護更新|
對于早期 linux 用戶,人們需下載和編譯源代碼來安裝軟件。
**如果有預先編譯好的軟件包,使用起來相對容易和快速一些**
擁有對軟件源代碼的訪問權限是linux的偉大之處,它賦予每個人定制和優化系統權利。
|包管理兩大陣營|發行版(部分列表)|包管理底層工具|包管理上層工具|
|---|---|---|---|
|.deb|Debian , Ubuntu|dpkg|apt-get, aptitude|
|.rpm|Fedora , CentOS , Red Hat , OpenSUSE |rpm|rpm|
以 ubuntu16為例:
- 查找安裝
命令 子命令 包名
apt install git
apt 命令首先分析 git 依賴關系,這就是包管理的好處.
如果程序發現缺少了一個依賴,則會報錯并退出。
```
Reading package lists... Done
Building dependency tree? ? ?
Reading state information... Done
The following packages were automatically installed and are no longer required:
? libllvm5.0 snapd-login-service
Use 'apt autoremove' to remove them.
Suggested packages:
? git-daemon-run | git-daemon-sysvinit git-doc git-el git-email
? git-gui gitk gitweb git-arch git-cvs git-mediawiki git-svn
The following NEW packages will be installed:
? git
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 3,176 kB of archives.
After this operation, 24.1 MB of additional disk space will be used.
Get:1 http://mirrors.tuna.tsinghua.edu.cn/ubuntu xenial-updates/main amd64 git amd64 1:2.7.4-0ubuntu1.6 [3,176 kB]
Fetched 3,176 kB in 3s (878 kB/s)
Selecting previously unselected package git.
(Reading database ... 241828 files and directories currently installed.)
Preparing to unpack .../git_1%3a2.7.4-0ubuntu1.6_amd64.deb ...
Unpacking git (1:2.7.4-0ubuntu1.6) ...
Setting up git (1:2.7.4-0ubuntu1.6) ...
```
- 卸載
命令 子命令 包名
apt remove git
y
```
Reading package lists... Done
Building dependency tree? ? ?
Reading state information... Done
The following packages were automatically installed and are no longer required:
? liberror-perl libllvm5.0 snapd-login-service
Use 'apt autoremove' to remove them.
The following packages will be REMOVED:
? git git-core
0 upgraded, 0 newly installed, 2 to remove and 0 not upgraded.
After this operation, 24.1 MB disk space will be freed.
Do you want to continue? [Y/n] y
(Reading database ... 242467 files and directories currently installed.)
Removing git-core (1:2.7.4-0ubuntu1.6) ...
Removing git (1:2.7.4-0ubuntu1.6) ...
```
- 更新
apt update 更新源
更新已安裝的包
命令 子命令 包名
apt upgrade git
```
Reading package lists... Done
Building dependency tree? ? ?
Reading state information... Done
git is already the newest version (1:2.7.4-0ubuntu1.6).
Calculating upgrade... Done
The following packages were automatically installed and are no longer required:
? libllvm5.0 snapd-login-service
Use 'apt autoremove' to remove them.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
```
- 顯示包信息
知道包名后,要顯示軟件包的詳細信息,例如:版本號、大小、校驗值和軟件描述等信息時。
apt-cache show firefox
```
Package: firefox
Architecture: amd64
Version: 67.0.4+build1-0ubuntu0.16.04.1
Priority: optional
Section: web
Origin: Ubuntu
...
```
列出所有已經安裝的軟件包
apt list --installed
```
Listing... Done
a11y-profile-manager-indicator/xenial,xenial,xenial,now 0.1.10-0ubuntu3 amd64 [installed]
account-plugin-facebook/xenial,xenial,xenial,xenial,xenial,xenial,now 0.12+16.04.20160126-0ubuntu1 all [installed]
...
firefox/xenial-updates,xenial-security,xenial-updates,xenial-security,xenial-security,xenial-updates,now 67.0.4+build1-0ubuntu0.16.04.1 amd64 [installed]
...
```
PS:**aptitude**與 apt-get 一樣,是 Debian 及其衍生系統中功能極其強大的包管理工具。
與 apt-get 不同的是,aptitude在處理依賴問題上更佳一些。
## 編譯程序make
編譯就是把源碼(一個由程序員編寫的人類可讀的程序的說明)翻譯成計算機處理器的語言的過程。
ubuntu16 下,編譯一個叫做 diction 的程序,來自 GNU 項目。步驟:
(1)安裝**編譯器**
>sudo apt install ftp gcc
安裝 ftp 與 gcc 兩個文件。
(2)獲取**源代碼**
>ftp ftp.gnu.org
```
Connected to ftp.gnu.org.
220 GNU FTP server ready.
Name (ftp.gnu.org:root): anonymous
230-NOTICE (Updated October 13 2017):
...
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
...
-rw-r--r--? ? 1 0? ? ? ? 0? ? ? ? ? ? 2925 Apr 04 20:15 README
-rw-r--r--? ? 1 0? ? ? ? 0? ? ? ? ? 405121 Oct 23? 2003 before-2003-08-01.md5sums.asc
-rw-rw-r--? ? 1 0? ? ? ? 3003? ? ? 262986 Jul 05 09:50 find.txt.gz
drwxrwxr-x? 320 0? ? ? ? 3003? ? ? ? 12288 Jun 17 21:54 gnu
drwxrwxr-x? ? 3 0? ? ? ? 3003? ? ? ? 4096 Mar 10? 2011 gnu+linux-distros
-rw-rw-r--? ? 1 0? ? ? ? 3003? ? ? 483088 Jul 05 09:50 ls-lrRt.txt.gz
drwxr-xr-x? ? 3 0? ? ? ? 0? ? ? ? ? ? 4096 Apr 20? 2005 mirrors
lrwxrwxrwx? ? 1 0? ? ? ? 0? ? ? ? ? ? ? 11 Apr 15? 2004 non-gnu -> gnu/non-gnu
...
226 Directory send OK.
ftp> cd gnu/dicition
550 Failed to change directory.
ftp> cd gnu/diction
250 Directory successfully changed.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r--? ? 1 3003? ? 65534? ? ? 68940 Aug 28? 1998 diction-0.7.tar.gz
-rw-r--r--? ? 1 3003? ? 65534? ? ? 90957 Mar 04? 2002 diction-1.02.tar.gz
-rw-r--r--? ? 1 3003? ? 65534? ? ? 141062 Sep 17? 2007 diction-1.11.tar.gz
-rw-r--r--? ? 1 3003? ? 65534? ? ? ? 189 Sep 17? 2007 diction-1.11.tar.gz.sig
226 Directory send OK.
ftp> get diction-1.11.tar.gz
local: diction-1.11.tar.gz remote: diction-1.11.tar.gz
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for diction-1.11.tar.gz (141062 bytes).
226 Transfer complete.
141062 bytes received in 1.99 secs (69.1985 kB/s)
ftp> bye
221 Goodbye.
此時根目錄下多了個壓縮包
diction-1.11.tar.gz
```
解壓縮文件
>tar xzf diction-1.11.tar.gz
(3)查看代碼
*.c與*.h文件
(4)編譯**預處理**
執行 configure 預處理文件=>產生 makefile腳本文件
>./configure
(5)**編譯**程序
>make
執行命令 make 會直接找 makefile=>創建很多 .o 文件
(6)**安裝**程序
>sudo make install
(7)**查看**程序**是否安裝好**
> which diction?
/usr/local/bin/diction
|編譯原因|內容|
|---|---|
|可用性|有些發行版不包含所有程序|
|即時性|獲得最新版本程序|
# shell眼中看世界——“展開”
當按下 enter 鍵后,發生在命令行中的一些“魔法”,這種**魔法**就是**展開的過程**。
## 字符展開
>echo *
打印出當前目錄下的所有文件夾名,不會顯示隱藏文件。
當回車鍵被按下時,shell 在命令被執行前在命令行上自動展開任何符合條件的字符, 所以 echo 命令的實際參數并不是”*“,而是它展開后的結果。
## 路徑名展開
>echo /usr/*/share
```
/usr/kerberos/share? /usr/local/share
```
通配符所依賴的工作機制叫做路徑名展開。
## 波浪線展開
波浪線字符(“~”)有特殊的含義。
>[Teenie@wutiantian.github.io ~]$ echo ~teenie
/home/teenie
當它用在 一個單詞的開頭時,它會展開成指定用戶的家目錄名,如果沒有指定用戶名,則展開成當前用戶的家目錄
## 算術表達式展開
shell 在展開中執行算數表達式。當作計算器來使用。
算術表達式展開使用這種格式:
>$((expression))
表達式是指算術表達式,它由數值和算術操作符組成。
**注意:美元符號不能丟掉!**
例如
>echo $((2+2))
4
算術表達式**只支持整數**(全部是數字,**不帶小數點**),但是能執行很多不同的操作。
|操作符|說明|
|---|---|
|+| ????加|
|-| ????減|
|*| ????乘|
|/| ????除(但是記住,因為展開只是支持整數除法,所以結果是整數。)|
|%| ????取余,只是簡單的意味著,“余數”|
|**| ???取冪|
在算術表達式中**空格并不重要**,并且**表達式可以嵌套**。例如,5的平方乘以3:
注意:嵌套的$與括號切不可少!否則報錯!!!
```
echo $(($((5**2))*3))
75
echo with $((5%2)) left over.
with 1 left over.
```
## 花括號展開
這種模式不能 嵌入空白字符。?
花括號展開可以嵌套。?
```
花括號的模式中 創建多個文本字符串。?
echo Front-{A,B,C}-Back
Front-A-Back Front-B-Back Front-C-Back
echo Number_{1..5}
Number_1 Number_2 Number_3 Number_4 Number_5
使用了一個整數區間
echo {Z..A}
Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
倒序排列的字母區間
echo a{A{1,2},B{3,4}}b
aA1b aA2b aB3b aB4b
花括號展開可以嵌套
```
## 參數展開
**參數展開特性在 shell 腳本中比直接在命令行中更有用。**
存儲小塊數據,并給每塊數據命名的能力有關系。許多像這樣的小塊數據, 更恰當的稱呼應該是變量,可供你方便地檢查它們。
```
"USER"的變量包含你的用戶名。可以這樣做來調用參數,并查看 USER 中的內容
echo $USER
teenie
查看有效的變量列表
printenv |less
```
**其它展開類型中,如果你誤輸入一個字符,展開就不會發生**。
這時 echo 命令只簡單地顯示誤鍵入的模式。
但在參數展開中,如果你拼寫錯了一個變量名, 展開仍然會進行,只是展開的結果是一個空字符串。
## 命令(展開)替換
命令替換允許我們把一個命令的**輸出作為一個展開模式來使用**
```
ls -l $(which cp)
-rwxr-xr-x 1 root root 151024 3月? 3? 2017 /bin/cp
把 which cp 的執行結果作為一個參數傳遞給 ls 命令,因此可以在不知道 cp 命令 完整路徑名的情況下得到它的文件屬性列表。
file $(ls /usr/bin/* | grep zip)
/usr/bin/funzip:? ? ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 2.6.32, BuildID[sha1]=06412c648a6927c4a14c751fe2412db3425ecd0f, stripped
/usr/bin/gpg-zip:? ? POSIX shell script, ASCII text executable
...
管道線的輸出結果成為 file 命令的參數列表
```
## 引用-控制展開
**shell 提供了一種叫做引用的機制,來有選擇地禁止不需要的展開。**
```
echo this is a? ? test
this is a test
shell 利用單詞分割刪除掉 echo 命令的參數列表中多余的空格
echo The total is $100.00
The total is nu00.00
echo The total is $00.00
The total is bash0.00
echo The total is$100.00
The total isnu00.00
因為 1 是沒有定義的變量,參數展開把 $1 的值替換為 nu
echo the winner is $smith
the winner is
```
## 引用-雙引號-限制部分展開
把文本放在雙引號中, shell 使用的**特殊字符,都失去它們的特殊含義,被當作普通字符來看待**。
有幾個例外: $,\ (反斜杠),和 `(倒引號)。
這意味著單詞分割、路徑名展開、 波浪線展開和花括號展開都將失效,然而**參數展開、算術展開和命令替換 仍然執行**。
使用雙引號,我們可以**處理包含空格的文件名。**
```
比方說我們是不幸的 名為 two words.txt 文件的受害者。
如果我們試圖在命令行中使用這個 文件,單詞分割機制會導致這個文件名被看作兩個獨自的參數,而不是所期望 的單個參數:
ls -l two words.txt
ls: cannot access two: No such file or directory
ls: cannot access words.txt: No such file or directory
使用雙引號,我們可以阻止單詞分割,得到期望的結果;
進一步,我們甚至可以修復 破損的文件名。
ls -l "two words.txt"
-rw-rw-r-- 1 me? me? 18 2008-02-20 13:03 two words.txt
mv "two words.txt" two_words.txt
```
記住,在雙引號中,參數展開、算術表達式展開和命令替換仍然有效:
```
echo "$USER$((2+2))"
teenie4
```
單詞分割機制會在單詞中尋找空格,制表符,和換行符,并把它們看作 單詞之間的界定符。
這意味著無引用的空格,制表符和換行符都不是文本的一部分, 它們只作為分隔符使用。
```
echo "this is a? ? test"
this is a? ? test
```
單詞分割被禁止,內嵌的空格也不會被當作界定符,它們成為參數的一部分。
一旦加上雙引號,我們的命令行就包含一個帶有一個參數的命令。
```
單詞分割機制把換行符看作界定符,對命令替換產生了一個雖然微妙但有趣的影響
echo $(cal)
六月 2019 日 一 二 三 四 五 六 1 2? 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
echo "$(cal)"
? ? ? 六月 2019? ? ? ?
日? 一 二 三 四? 五 六?
? ? ? ? ? ? ? ? ? 1? ? ?
2? 3? 4? 5? 6? 7? 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29? ? ? ? ?
30? ? ? ? ? ? ? ? ? ?
命令行只有一個參數,參數中包括嵌入的空格和換行符。
```
## 引用-單引號-禁止展開
如果需要禁止所有的展開,我們要使用單引號。以下例子是無引用,雙引號,和單引號的比較結果
```
echo text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
text /home/teenie/*.txt a b foo 4 teenie
echo "text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER"
text ~/*.txt {a,b} foo 4 teenie
echo 'text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER'
text ~/*.txt {a,b} $(echo foo) $((2+2)) $USER
```
## 轉義字符
**如果沒有準確地理解展開模式,shell 總是神秘和混亂的源泉,并且 shell 潛在的能力也 浪費掉了。**
只想引用單個字符。
**在字符之前加上一個反斜杠,叫做轉義字符。**
經常在雙引號中使用轉義字符,來**有選擇地阻止展開**。
使用轉義字符來*消除文件名中一個字符的特殊含義*,是很普遍的。?
這些字符包括”$”, “!”, “ “等字符。
```
echo "The balance for user $USER is: \$5.00"
The balance for user teenie is: $5.00
防止美元符號展開
```