本文介紹最基礎的Linux Shell指令,是最基礎的第一篇章,考量到大部分的人都是從Windows作業系統開始學習電腦,因此在講解的時候我會盡量加入Windows的類似功能來當作範例講解。

基本原理

初見Linux指令可能會覺得複雜,充滿英文,而且也不是按照英文文法運作,還充滿奇怪的縮寫。其實Linux的指令大致上都遵循著固定的格式運作,就像是Linux本身的文法一樣。一行指令大致上有以下三個部分。

程式名稱相關設定目標資料

以下先來幾個範例,體驗一下。

# 顯示目前位置底下的檔案與資料夾(只有程式名稱)
$ ls

# 同上,但是以清單方式顯示(程式資料+相關設定)
$ ls -l

# 刪除test.txt檔案(程式名稱+目標資料)
$ rm test.txt

# 刪除text資料夾與底下所有檔案(程式名稱+相關設定+目標資料)
$ rm -r test

# 遠端登入到另一台Linux(程式名稱+目標資料)
$ ssh 192.168.0.1

# 透過Java執行Java程式碼(程式名稱+目標資料)
$ java HelloWorld

在本篇教學中,範例程式碼的區塊內會看到#開頭的文字,這代表是註解,也就是說名用的。看到$開頭的文字代表是指令,但是你要複製指令的話記得不要連$都一起複製囉。

基本路徑操控

pwd

pwd看起來有點像是passwd(密碼)的縮寫,但其實是「Print Work Directory」的縮寫,用來顯示目前使用者所在的資料夾。在上一篇基本原理的時候有提過,指令的最後面通常是接目標資料,可能是一個檔案或是一個目錄,因此透過pwd確認目前所在位置是很重要的喔!

順便提到Print或是列印,在中文中會覺得是要將文字或圖片列印在紙張上面,但其實在文字介面中提到列印的時候通常代表「顯示在螢幕上」,這點也是初學的時候容易誤會要注意一下。

cd

cd是「Change Directory」的縮寫,用來切換目前所在的工作目錄。

這邊要先簡單的說明一下相對位置絕對位置的概念,以大部分的人比較習慣的Windows來舉例,絕對目錄的檔名路徑就像是:C:\Users\kyle\abc.txt相對目錄中的一個叫做abc.txt的檔案,

  • . 一個點就是現在位置的別稱,因此輸入cd .之後,什麼也不會改變。
  • .. 兩個點是上一層位置的別稱,輸入cd ..之後就會一到上一層。注意上一層與上一頁是不同的。
  • ~ 波折號代表家目錄,Windows上也有一個使用者家目錄,底下有音樂、下載、文件…的那個資料夾。
  • / 斜線代表根目錄,在Windows上就像你點開C槽或D槽看到的資料夾,但Linux只有一個根目錄。

題外話以前看到cd就會想到光碟片的CD,但cd這個指令出現時光碟CD可能還沒出現。如今現在很多人的生活中都看不到光碟CD了,但cd依然在Windows、Linux、macOS上,而且他們的功能都一樣是切換目錄😁。

$ pwd      # 顯示 /home/kyle
$ cd ..
$ pwd      # 顯示 /home
$ cd jack
$ pwd      # 顯示 /home/jack
$ cd ~
$ pwd      # 顯示 /home/kyle
$ cd ~/music
$ pwd      # 顯示 /home/kyle/music

ls

ls是list的縮寫,用來在螢幕上列出目前所在目錄的檔案與資料夾。順帶一題在Windows的CMD與PowerShell上面,有一個指令叫做dir,功能等同Linux與macOS上的ls。

通常ls指令都默認顯示顏色,方便區分:

  • 白色:檔案
  • 綠色:可執行的檔案
  • 藍色:資料夾
  • 黃色:設備檔,例如/dev/sba
  • 淺藍色:連結檔,類似Windows的捷徑
  • 綠底黑字:所有人都可讀寫的目錄
  • 粉紅色:Socket,應用程式溝通用的
  • 金色:Process 行程

會有這麼多奇奇怪怪的東西是因為,不管是檔案、資料夾還是其他東西,在Linux裡面其實都當成一種檔案來看待。

在Linux與Mac裡面,使用.開頭的檔案代表隱藏檔,通常是一些設定檔、暫存檔,並不是真的要隱藏到令人找不到,只是為了整潔一點不顯示而已。如果想看到隱藏檔只需要加上-a即可,例如ls -a

在預設情況下使用ls只會顯示檔案名稱或資料夾名稱,如果需要看到詳細資訊,可以使用ls -l。如果需要詳細資訊,而且連同隱藏檔案一起顯示,可以縮寫為ls -al。如果希望詳細資訊中的檔案大小不要顯示位元組,而是自動依照大小切換成KB、MB、GB,可以使用ls -alh。需要注意資料夾總是顯示4KB,ls指令不會計算資料夾裡面有多少檔案。

我們在家目錄輸入ls -alh可以看到家目錄的檔案,通常至少會輸出以下內容。

drwxr-xr-x 6 kyle kyle 4.0K Sep 29 17:22 .
drwxr-xr-x 5 root root 4.0K May 13 22:26 ..
-rw------- 1 kyle kyle  22K Sep 29 17:26 .bash_history
-rw-r--r-- 1 kyle kyle 3.5K May 14 18:22 .bashrc

首先第一行最前面看到drwxr-xr-x,d代表資料夾,後面一串是檔案權限相關的說明,之後會開一篇檔案權限詳解來解釋。然後會看到kyle kyle代表這個檔案或資料夾是屬於kyle帳號與kyle群組的,這也是跟檔案權限有關係。再來4.0K就是佔據的大小,因為是資料夾所以總是顯示4KB。然後Sep 29 17:22是最後修改時間。

每一行的最後面顯示這個檔案/資料夾的名稱,第一行叫做.代表是現在所在的資料夾,第二行的..代表是這個資料夾的上一層資料夾。從第三行開始才是這個資料夾裡面真正裝著的檔案與子資料夾。


基本檔案操控

touch

一些常見的教學中會說touch是建立一個空白檔案,這的確是使用touch的常見原因。但touch還有一個功用是,如果檔案已經建立了,touch會將檔案的最後更新時間變為現在時間,可以搭配上一章節提到的ls -l觀察檔案的最後更新時間。

例如建立一個檔案叫做abc.txt:touch abc.txt

cp

cp是Copy的縮寫,用於複製檔案或資料夾。cp需要兩個參數,基本使用方法就是cp 原本的檔名 新的檔名,參考以下範例。

# 複製abc.txt,並取名為abc2.txt
$ cp abc.txt abc2.txt

# 複製abc.txt到一個絕對位置
$ cp abc.txt /home/jack/abc.txt

# 複製一整個資料夾的資料
$ cp -r folder folder2

mv

mv是Move的縮寫,用來移動檔案與資料夾,也能拿來更改檔案與資料夾的名稱。mv需要兩個參數,移動的指令:mv 檔案名稱 新位置的資料夾名稱,修改檔名的指令:mv 檔案名稱 新的檔案名稱

要如何區分是移動還是修改檔名?對Linux來說是檔案還是資料夾、是移動還是更改名稱的指令都是一樣的,一開始容易搞錯。我們重新看一下指令,可以這麼解釋:mv 參數1 參數2,首先參數1可以是檔案名稱也可以是資料夾,可以是絕對路徑也可以是相對路徑。然後參數2是重點,如果參數2是一個資料夾,代表要將參數1移動到資料夾裡面,如果參數2是不存在的路徑,代表要將參數1改名字變成參數2。

狀況參數1參數2說明
移動資料夾資料夾資料夾將參數1(資料夾)放到參數2(資料夾)裡面
資料夾檔案操作無效
更名資料夾資料夾不存在將參數1(資料夾)更改名稱為參數2
移動檔案檔案資料夾將參數1(檔案)放到參數2(資料夾)裡面
覆蓋檔案檔案檔案將參數1(檔案)覆蓋掉參數2(檔案)
更名檔案檔案不存在將參數1(檔案)更改名稱為參數2

其中「覆蓋檔案」的狀況要非常小心地使用,因為被覆蓋掉的檔案很難找回來囉。

rm

rm是Remove的縮寫,用來刪除檔案與資料夾。被rm指令刪掉的檔案不會進到垃圾桶、資源回收桶之類的地方,非常難找回來,要小心使用。

如果要刪除資料夾,而且資料夾裡面的檔案也要一併刪除,需要加上r的旗標,例如:rm -r dir

如果刪除資料夾與裡面的檔案,而且不要一個個詢問你是否要刪除,可以使用:rm -rf dir

mkdir

建立資料夾,是Make Directory的縮寫。

例如建立一個叫做abc的資料夾:mkdir abc

rmdir

刪除資料夾,是Remove Directory的縮寫。只能刪除空的資料夾,資料夾內不能有東西。如果要將資料夾與裡面的所有東西都一起刪除,需要使用上面提到的rm -rf 路徑指令。

例如建立一個叫做abc的資料夾:rmdir abc

文字檔案操控

大部分時候我們會將檔案分為二進位檔案與文字檔案。區分的邏輯很簡單,不是文字檔案的就是二進位檔案。例如txt、csv、html、xml都是文字檔案,但是要注意word、excel之類的檔案是二進位檔案,因為他有一些特殊規則在裡面,沒辦法直接當成文字檔案處理。

對電腦底層的硬體來說,所有檔案都是0與1組成的,因此文字檔案其實也是二進位檔案,差別在於Linux對文字檔案可以有一些特別的操作。因此在了解基本檔案操作之後,我們可以學習針對文字檔案的更多操作方式囉。

cat

這個指令後面需要接一個檔案名稱,會將檔案內的文字全部顯示在螢幕

上。可以用-n旗標指令要求顯示每一行是第幾行。

# 顯示log.txt的內容
$ cat log.txt
abc
abc
abc

# 加上行數顯示log.txt的內容
$ cat -n log.txt
1 abc
2 abc
3 abc

head

這個指令等於是cat的進階版,可以限制只顯示某個檔案的前10行顯示內容。也可以加上-n來指定要顯示多少行,例如顯示20行:head -n 20 檔案名稱

tail

這個指令跟head相反,是將檔案的最後10行顯示出來。例如一些日誌檔案都是越下面的越新,使用tail就會很方便的直接看到最新到日誌是什麼。我們可以用tail -n 20 檔案名稱來指定要看最後20行文字。

另外tail還有一個非常棒的功能,就是持續輸出檔案內的最新內容。例如有一個日誌檔案叫做log.txt,他每隔幾秒就會多一行新的資料在裡面,我們豈不是要每隔幾秒就用tail指令看一次裡面才能知道最新狀況嗎?但我們只需要輸入一次tail -f log.txt來持續監控log.txt檔案的變化,每當log.txt多一行資料,tail就會自動顯示一行資料,一直到我們在鍵盤按下Ctrl + C停止它,是非常方便的功能。

echo

在英文中echo是回音、幫腔的意思,因此這個指令就是你帶什麼參數給他,他就回覆什麼參數。例如你輸入echo hello螢幕就會顯示hello。看起來好像很廢😁但是他配Linux的一些特殊操作讓他有特殊功能,下面舉一些例子。

# 在螢幕顯示「Hello」
$ echo Hello
Hello

# 將「Hello」儲存到檔案word.txt裡面(覆蓋原始檔案)
$ echo Hello > word.txt

# 將「Hello」儲存到檔案word.txt裡面(不覆蓋而是添加到同一份檔案的尾端)
$ echo Hello >> word.txt

在這邊先了解一下有這個指令就可以了,很多進階的操作需要搭配其他指令,之後會陸續講到喔。

vim與nano

vim與nano會直接開啟一個純文字的文字編輯器來編寫文字檔案,vim比較複雜,Ubuntu裡面甚至預設沒有安裝完整版的vim,建議可以從nano開始學習。

因為教學篇幅太長,所以會另外再寫一篇。這邊先告訴各位最簡單的nano用法,就是nano 檔案名稱,如果檔案名稱是已存在的就會編輯舊檔案,如果檔案名稱不存在就會建立新檔案。編輯完成按下Ctrl + X就會問你要不要存擋,輸入Y或是N按下Enter即可。如果你回答要存擋,他就會問你要不要修改檔案名稱,這邊什麼都不打直接按下Enter即可完成。

帳號操控

sudo

使用root權限(系統最高權限)執行命令,類似在Windows上一個選項。使用方式是在指令最前面加上sudo,例如sudo mkdir abc。root可以不受Linux的權限檢查,有些人會將Android刷機獲取root權限,就是指獲得root帳號的權限。

passwd

修改登入密碼。

# 修改自己的密碼
$ passwd
Current password: 

# 修改jack的密碼(需要有管理權限)
$ passwd jack
passwd: You may not view or modify password information for jack.

su

用來切換帳號,是Switch user的縮寫。輸入帳號密碼後登入Linux,當下的身份與權限就是跟隨登入所輸入的帳號。如果在登入後還想登入其他帳號,可以使用su指令,

# 從原本帳號切換到jack的帳號,系統會要求輸入jack的密碼
$ su jack
Password:

users

列出目前正在登入中的使用者帳號,因為一個帳號同時從兩個地方登入,所以同一個帳號可能會出現多次。

# 從個人電腦開兩個ssh視窗都登入同一台電腦的同一個帳號
$ users
kyle kyle

whoami

這個指令其實就是「Who am I」我是誰😂,作用也很簡單,會顯示目前登入的使用者名稱。

$ whoami
kyle
$ sudo su
$ whoami
root

newgrp

初始群組(Initial group)切換有效群組(Effective group)。一個帳號會存在一個初始群組,剛登入的時候就會在這個群組內。但同時帳號也能所屬於其他群組,稱作有效群組,可以透過newgrp指令切換到其他身份。切換後使用touch、mkdir之類的指令時,建立的檔案與資料夾的身份就會不太一樣。

# 建立檔案名為test1,然後瀏覽資料夾內的檔案
$ touch test1 && ls -l
-rw-r--r-- 1 kyle kyle   0 Jun  9 10:52 test1

# 切換群組後再次建立黨名,取為test2,可觀察兩個檔案的群組差別
$ newgrp docker
$ touch test2 && ls -l
-rw-r--r-- 1 kyle kyle   0 Jun  9 10:52 test1
-rw-r--r-- 1 kyle docker 0 Jun  9 10:52 test2

exit

Exit指令用來離開目前登入的狀態,具體來說離開哪理呢?這比較複雜,要看自己在哪個shell,有時候恍神忘了自己直接離開到退出SSH。但透過免密碼的ssh登入,一個指令就登入回去了。可透過下面範例觀察exit的作用。

# 透過ssh遠端登入到Linux先看目前身份
$ id
uid=1000(kyle) gid=1000(kyle) groups=1000(kyle),997(docker)

# 切換群組後再觀看目前身份
$ newgrp docker && id
uid=1000(kyle) gid=997(docker) groups=997(docker),1000(kyle)

# 切換到root帳號後再觀看目前身份
$ sudo su && id
uid=0(root) gid=0(root) groups=0(root)

# 以下開始執行exit指令,再觀看目前身份,從root變回上一個身份
$ exit && id
uid=1000(kyle) gid=997(docker) groups=997(docker),1000(kyle)

# 再次exit連群組都退回原本的主要群組
$ exit && id
uid=1000(kyle) gid=1000(kyle) groups=1000(kyle),997(docker)

# 第三次exit會退出ssh遠端登入,回到原本的電腦上
$ exit
logout

電源操控

shutdown

關閉電腦,使用範例:sudo shutdown -h now

reboot

重新開機,使用範例:sudo reboot