基礎 Linux(UNIX-Like) 指令(Command line)整理介紹

什麼是Command line?
就是常常我們看電影中,駭客對著一個沒有圖且畫面全黑的電腦打著滿滿文字,看起來很帥的那個。
(翻攝於youtube)
阿不對放錯圖了XD,應該是這張才對
(電影 ALGORITHM: The Hacker Movie中照片)

那個輸入的視窗,在 windows中稱為 命令提示字元(cmd);在 Linux 中則稱為 終端機(terminal)。至於輸入的那些指令則稱為command line(cl)。
這些指令其實是呼叫一些現成寫好的程式,因此若能善用這些指令,有時候可以省去很多不必要的碼農時間。

這邊提供了一些基本但重要且常用的Linux指令(windows的與linux大不相同),介紹其常用的功能,若想知道該指令更多細節與參數,可以善用man 或者 --help指令進行查詢,例如:
$ man cat
$ cat --help 
就能得到更多的細節拉~

在開始介紹指令以前,先講解一下指令的參數(option)
一般而言參數可以分為長參數(long option)短參數(short option)
長參數:在使用時常用' -- '作為參數開始,並且是一串具有意義的單字,較具有可讀性,缺點則是過長。例如--help --all或者--recursive。
短參數:在使用時都用' - '作為參數開始,接著使用一個英文字母來表示,通常是某個單字的其中一個字母。例如-a -l或者-r之類的。
另外短參數可以合併在一起使用,例如:
$ ls -la

$ ls -l -a
就是一樣的東西。更加詳細的原理可以參考getopt_long()。

以下開始介紹各個常用指令,有黃底的代表筆者認為非常重要一定要熟悉的指令。

cat (concatenate) 🐱
<用處> 印出檔案內容或將多個檔案合併
<語法> cat [OPTION]... [FILE]...
<說明> 此語法多用於將文字檔案內容印在terminal上。實際上該指令是將檔案內容連結(複製)至另一端,在沒有指定目標的情況下,會將檔案連結至standard output,即印在terminal上。
若要將file1的內容連結至file2的話,可以使用以下指令。
$ cat file1 > file2
該指令會將file1的檔案內容,取代file2中的檔案內容。另外指令中的 > 是terminal中的特殊符號,稱為重導向 (redirect),會在之後做介紹。
該指令也可以將複數個檔案連結至新的檔案,只要重複輸入檔名即可。
$ cat file1 file3 > file2
若不想要後者檔案被完全取代掉,想用添加的,可以把redirect符號 > 改為 >>
$ cat file1 >> file2

cd(change directory)
<用處> 更改工作目錄(working directory)至目標。
<語法> cd DIRECTORY
<說明> 更改當前terminal的工作目錄。另外在目錄中會有 ... 兩種目錄,分別代表自身位置與其父目錄(上一頁)。DIRECTORY部分可以是絕對位置或相對位置(當前目錄資料夾)。
此指令將會將目錄轉至目錄grass中,若不存在則失敗。
$ cd grass 

cp(copy files)
<用處> 複製檔案。
<語法> cp [OPTION]... [-T] SOURCE DEST
<說明> 將檔案SOURCE複製一份到DEST,而DEST可以分為兩種:
第一種為DEST為目錄時,會將SOURCE複製到該目錄下,且檔名不會做修改。另外SOURCE可為複數個檔案。
$ cp cat.jpg ~/Desktop/ 
$ cp file1 file2 ~/  
第二種則是DEST為檔案時,就是將SOURCE複製到DEST的目錄下且檔名改為DEST的檔名。
$ cp cat.jpg ~/Pictures/cute.jpg 
另外若想要複製資料夾的話,則要加入參數 -r(recursive)
$ cp -r /usr/grass /usr/cat 

grep(Global Regular Expression Print)
<用處> 本文搜尋功能,可以在指定檔案中尋找特定字串
<語法> grep [OPTIONS] PATTERN [FILE...]
<說明> grep 指令會試著在FILE中搜尋與PATTERN相符文字。若找到,則回傳該行內容至terminal,且該字串會被上色。若目標FILE不止一個時,在顯示時會額外顯示檔名。PATTERN允許使用正規表示法(limited regular expression)。
$ grep 'grass' file1 file2  
PATTERN的引號可不用。
<參數>
以下介紹一些比較常用的參數:
    -b (block)  印出搜尋到的字串的那一行的byte offset,即該行以前有多少個byte(注意,換行符號算1byte)。
    -c (count) 印出搜尋到幾個PATTERN。不同檔案是分開計算。
    -d 若目標不為檔案,為目錄時必須添加。 或用 -r。
    -h 當檔案為複數時,不印出檔名
    -i (ignore) 比較PATTERN時在意大小寫區分。
    -l  印出有比對到的檔案檔名。因此若加上-c的話也只會出現檔名不會出現數量。
    -n (number) 印出搜尋到的字串的那一行的行數。(第一行的行數為1)。
    -s (silent)  若遇到不存在權限不足時,並不會印出錯誤訊息
    -v (revert) 印出不包含PATTERN的那行
該指令因為含有-c,將會把檔案中符合tag的的數量印出。
$ grep -c tag file.txt
這個方法可以對該目錄下所有副檔名為.c的檔案進行字串比對,找到所有包含main這個字串的檔案並且印出檔名。
$ grep -l main *.c


ln(link files)
<用處> 連結檔案或者給予檔案別名。
<語法> ln [OPTION]... [-T] TARGET LINK_NAME   (1st form)
以下只會會將file1丟到~(家目錄)下做軟連結,並叫做file2:
$ ln -s file1 ~/file2
<說明> ln分為硬連結 (hard link)軟連結 (symbolic link), 預設下是使用硬連結。以下是兩者差別:
  1. 硬連結本身是將原檔案進行副本,因此實際上是不會占用任何空間;軟連結類似於Windows 的捷徑,佔用非常些微的空間。
  2. 硬連結因為是以副本形式,兩者的inode會是一樣的。(inode是每個獨立檔案唯一的編號,用 ls -li 可以查看inode)。軟連結則兩者的inode會是不一樣的。
上圖雖然硬連結的檔案有大小,但實際上是不佔用空間的。
  3. 不能對目錄進行硬連結,僅限於檔案;軟連結可以對目錄進行連結
  4. 若在不同的檔案系統(File System)下,是不能進行硬連結的。例如ext4 -> ntfs 是不行的;但軟連結可以跨部同檔案系統。

  5. 若原始連結檔案被刪除後,硬連結不會斷掉,且內容仍存在。即使在原本的目錄下重建原始檔案(同名),其內容仍是之前那個檔案的。
上圖中可以發現,file_new的內容始終是 "this is file 1",表示file刪除後連結不復存在,該檔(file_new)自成一個獨立的檔案。
而file_news的內容會跟著file的內容改變,當file被刪掉後,其連結變為紅色表是失連。當檔案在次建立後,則表是其連結恢復。
<參數> 以下介紹一些比較常用的參數:
    -b 刪除,覆蓋以前建立的鏈結
    -d 允許super user製作目錄的硬鏈結
    -f 目標檔案存在時,強制移除
    -i 目標檔案存在時,提示用戶是否覆蓋
    -n 把軟連結視為一般目錄
    -s 使用軟鏈結
    -v 顯示處理過程

ls(list)
<用處> 列出目標目錄的內容。
<語法> ls [OPTION]... [FILE]...
<說明> 非常常用的指令,用於檢查該目錄的內容。
<參數>
   -a  顯示所有的檔案,包含隱藏檔(開頭為.的檔案,例如.bashrc)
   -A  顯示所有的檔案,但不會印出.與..
   -d  若後面接目錄名稱時,顯示該目錄的資料,而不是顯示該目錄下的所有檔案。例如 ls -ld Desktop ,會顯示Desktop目錄的資訊,而不是Desktop中檔案的資訊。
   -f  顯示時不排序(預設是透過檔名進行排序)。
   -F  在檔名後面顯示其資料類型(*代表可執行檔; /代表目錄;@代表軟連結;=代表socke; |代表 FIFO;。)。
   -h  將檔案容量加上單位(MB, KB, GB...)。
   -i  印出其inode
   -l  類似Windows中的詳細資訊,會列出檔案使用者、權限、檔案大小等資訊。
   -n  將擁有者與擁有群組以UID與GID顯示
   -r  將排序結果反向顯示。
   -R  連同目錄下所有子目錄內容一起列出來
   -S  以檔案容量大小排序
   -t  以時間排序
通常最常用的組合為 a+l
$ ls -la
當我們只想對某個檔案/目錄做顯示,可以在最後面加上檔案名稱,同時支援萬用符號*
$ ls -lia file*
以上指令會將檔案名稱前綴為file的檔案(file123, file.txt ...等),包含inode等資訊詳細印出。

mkdir(make directories)
<用處> 創造一個新的目錄。
<語法> mkdir [OPTION]... DIRECTORY...
<說明> 此語法顧名思義就是建立一個目錄資料夾。
<參數>
   -m 無視預設,直接設定目錄權限
   -p 可以透過遞迴的方式,建立多層目錄
建立一個權限為 777的目錄  ,名為grass
$ mkdir -m 777 grass
在該目錄下建立一整串的目錄/grass/cat/meow
$ mkdir -p grass/cat/meow

more
<用處> 一頁一頁的印出檔案內容。
<語法> more [OPTION] [FILE]
<說明> 顯示檔案內容時,若是少量的內容用cat就足以應付,但遇到內容龐大的檔案時,有時候不但翻找內容不易,也有可能最上面的被ternimal吃掉。雖然用文字編輯器是最方便的,但其實用more也能達到該功能唷。
<使用方法>
   空白鍵 後一頁(行數即為螢幕大小)。
   b前一頁
   Enter 向下一行。
   /字串 在接下來的內容中,搜尋字串
   = 顯示目前行數。
   :f 顯示出檔名以及目前行數。
   . 重複上一個指令,多在搜尋完一次後搭配使用,免於再打一次搜尋的字串。
   q 離開檔案顯示。

mv(move files)
<用處> 移動檔案或者檔案改名。
<語法> mv [OPTION]... SOURCE... DIRECTORY
<說明> 移動檔案時的指令,若目標為不含目錄時,其功能等同於更改檔案名稱
$ mv cat.jpg ~/picture
以下指令會將a.out改名為exefile
$ mv a.out exefile 

od(octal dump)
<用處> 將檔案內容以八進制方法顯示。
<語法> od [OPTION]... [FILE]...
<說明> 檔案預設開啟都是以ASCII顯示,因此若有些binary的檔案用cat或者vi之類的打開時會顯示出亂碼。此時就可以用od指令將該檔案內容印出。顯示時第一行為Byte Offset。
<參數>
   -t 格式 (或 --format=格式)  指定顯示格式,後面必須再加上指定格式。
     格式應用:
        -t a(或 -a)  已預設的格式顯示,連空白、換行都會顯示字元。
        -t c(或 -c)  以ASCII字元方式印出,特殊字元會以跳脫字元( Escaped character)顯示,例如換行是\n。
        -t d[size]  以十進位(decimal)來輸出資料,每個整數佔用 size bytes。
        -t f[size]  以浮點數(floating)來輸出資料,每個浮點數佔用 size bytes。
        -t o[size]  以八進位(octal)來輸出資料,每個整數佔用 size bytes。
        -t x[size]  以十六進位(hexadecimal)來輸出資料,每個整數佔用 size bytes。
   -i  以int的形式輸出資料。
   -j  n 跳過n個字元再顯示。
   -l  以long的形式輸出資料。

因為此指令相較起來不常用,因此只放簡單的例子。以下是使用單字元(d1)進行十進制顯示:
$ od -t d1 file1

pwd(print working directory)
<用處> 印出當前工作目錄的名稱
<語法> pwd
<說明> 此指令可以印出目前工作目錄的路徑,是一個常在shell中使用的指令。
$ pwd

rm(remove files)
<用處> 移除檔案或目錄(需要加-r)
<語法> rm [OPTION]... [FILE]...
<說明> 用來移除檔案以及目錄,此指令必須謹慎使用,前一陣子就有一家伺服器提供者不小心用此指令把他的客戶資料都刪光光...,因此在使用此指令時必須小心一點。
<參數>
   -f (--force) 強制刪除,不會詢問確認與否與顯示錯誤訊息。
   -i 在刪除檔案前,會再次詢問使用者是否刪除,必須鍵入y或yes才會刪除。有-f時,-i不作用。
   -r (--recursive)  使用此參數時,若[FILE]部分為目錄,將可對其目錄進行刪除。
在以下指令,若 test為一資料夾,會將其資料夾包含其內檔案全部移除。
$ rm -r test
以下則是絕對不要輕易執行的禁忌指令:
1. 刪除根目錄下所有檔案與目錄,也就是把整個系統都刪掉!
$ rm -rf /
2. 刪除當前目錄下所有檔案與目錄。
$ rm -rf *
3. 刪除整個目錄,比上一個指令多一個把自己刪掉的動作,直接屍骨無存。
$ rm -rf .
以上指令千千萬萬不要在自己的電腦上隨便執行,想去測試可以開一個VM來玩看看XD。

rmdir(remove directory) 
<用處> 移除空目錄。
<語法> rmdir [OPTION]... DIRECTORY...
<說明> 只能對空目錄進行移除,若裡面有任何檔案救會執行失敗,且不存在-f之類的參數,因此不是很常會使用到的指令。


touch
<用處> 更改檔案的存取與修改時間(多用於make),又或用於創建一個新的空檔(快速建檔)。
<語法> touch [OPTION]... FILE...
<說明> 通常此指令多用於更改時間戳章(timestamp),或者快速建立一個檔案。
<參數>
   -a 只更改存取(access)時間
   -c (--no-create) 不建立任何檔案
   -d (--date=STRING) 使用指定的日期時間(STRING),而不是現在的時間
   -m 只更改修改(modification)時間
   -r (--reference=FILE) 以FILE為參考,將時間修改到與他一樣。
   -t STAMP 使用格式[[CC]YY]MMDDhhmm[.ss],而非現在的時間。
           格式有[]者代表可以省略,CC為世紀(20XX) YY為年 (XX17) .ss為秒
   --time=WORD 修改特定的日期時間,
       當WORD是access, atime或 use時,此指令等同於 -a
       當WORD是modify 或 mtime時,此指令等同於 -m

以下指令會建立名為logFile.log的檔案在目錄下;若該檔案存在的話,則修改其access與modification time。
$ touch logFile.log
加入-c後,只有在該檔案存在時修改時間,若不存在時,系統也不會建立新的檔案。
$ touch -c logFile.log
以下指令會將檔案的access與modification time都改成 2017/4/1 10:30:32 。17部分也可以打2017。
$ touch -t 1704011030.32 logFile.log

wc(word count)
<用處> 計算檔案中的行數、字數與字元數。
<語法> wc [OPTION]... [FILE]...
<說明> 該指令可以用於計算目標檔案的行數字數字元數以及bytes數。
<參數>
   -c(--bytes) 只顯示byte數目。
   -m(--chars) 只顯示字元數。
   -l(--lines) 只顯示行數。
   -L(--max-line-length) 顯示檔案中最長列的字元數。
   -w(--words) 只顯示字數。

pipe 
<用處> 將兩個程式串接起來,把前面程式的輸出當作下一個程式的輸入。
<語法> 程式A | 程式B
<說明> 一個程式預設下會開啟三個檔案(file descriptor, fd),分別是stdin(standard input)、stdout(standard output)與stderr(standard error)。
當在執行指令或者寫shell script時,常常會使用 | 這個pipe,將前者程式的stdout當作後者程式的stdin執行,如下指令可以將/etc內的檔案做計數(幾行-3即為幾個檔案,第一行是寫total,二三則是.與..,可把-a 改-A,就只要-1)。
$ ls -la /etc | wc -l


 至於fd相關與重導向,或許之後會在寫一篇解釋(有時間的話XD)。



留言

張貼留言

這個網誌中的熱門文章

(C) 簡單搞懂指標(pointer)、指標陣列(pointers of array, int *foo[]) 與指向陣列的指標 (pointer to array, int (*bar)[])

(c/c++) Function Pointer函式指標兩三事 (Function Pointer 的 typedef 與 Array of Function Pointer)

(C++) 別再用dynamic array與pointer了! 趕快學STL的vector與iterator!