---
# System prepended metadata

title: MIT-Missing Semester Lecture 1
tags: [CS自學指南]

---

# MIT-Missing Semester Lecture 1: Course Overview + The Shell (2020)
> 課程影片：[英文字幕](https://www.youtube.com/playlist?list=PLyzOVJj3bHQuloKGG59rS43e29ro7I57J) / [中文字幕](https://space.bilibili.com/518734451/channel/seriesdetail?sid=3320015) / [課程其他資源中文版](https://missing-semester-cn.github.io/)

## ■ shell 是什麼？ ■
我們所熟悉的可視化界面，他的功能是非常有限的，因為你只能使用可視化界面他所提供的按鈕、滑動條、輸入區塊等等功能，所以當可視化界面的功能不足以我們去使用時，就需要透過shell來幫助我們達成。

> 補充：[Chapter 11 Shell 和 Shell Script](https://www.cyut.edu.tw/~ywfan/1109linux/201109chapter11shell%20script.htm)
> 
>所有的電腦都是由硬體和軟體構成的﹐而負責主要運算的部分就是所謂作業系統的核心(kernel)﹐kernel 必須能夠接受來自鍵盤的輸入﹐然後交由 CPU 進行處理﹐最後將執行結果輸出到螢幕上。
>
> 比方說﹐輸入 pwd 命令﹐我們知道這是 print working directory 的意思﹐但作為 kernel 來說﹐它並不知道 pwd 是什麼﹐這時候﹐shell 就會幫我們將 pwd 翻譯為 kernel 能理解的程式碼。所以﹐我們在使用電腦的時候﹐基本上就是和 shell 打交道﹐而不是直接和 kernel 溝通。
>
> 從字面來解析的話﹐shell 就是“殼”﹐kernel 就是“核”。shell 就是使用者和 kernel 之間的界面﹐將使用者下的命令翻譯給 kernel 處理﹐關係如下圖﹕
> ![](https://hackmd.io/_uploads/Hkkj5A15h.png)

幾乎每個平台都會提供不同形式的shell，這節課將會使用ourne Again SHell, 簡稱“bash” 。

## ■ 使用shell ■
當你打開terminal時，會看到通常只有一行字在頂部，這就是所謂的shell提示符（shell prompt），他包含了你的使用者名稱、機器的名稱，以及目前所在的路徑。以及一塊白白的（會閃爍的光標）等待著你的輸入。這就是shell prompt，你可以用他告訴shell你想做什麼。

![](https://hackmd.io/_uploads/H1Rno0Jq2.png)


### ▋ date
以上，這就是你與電腦互動的主要文本界面，透過shell prompt，你可以輸入命令，而命令最終會被shell解析。

例如你可以輸入`date`這program，可以得到以下的結果，他會顯示目前的日期與時間。

![](https://hackmd.io/_uploads/HJp1F5D9n.png)

### ▋ echo
你也可以在打上program時加上參數，這是修改program行為的一種方式，例如說有一個叫做`echo`的program，他可以print出你給予他的參數，而參數就是在program後方以空格分隔的東西，shell 會基於空格分割命令並進行解析。

這裡我們試著print出hello，而作法如下，`echo`是一個程式，後方`hello`則是參數。

![](https://hackmd.io/_uploads/SJQIqcw93.png)

這裡可以注意到，老師說參數是由空格去做分割的，那麼如果我的參數是由多個單詞所組成的，那該怎麼辦呢？

這裡有兩種方法：
1. 可以用「單or雙引號」來解決，這個時候`echo`接收到的參數便是`hello world`。

    ![](https://hackmd.io/_uploads/rk-IiqD9h.png)

2. 可以用「反斜線 \ 」來解決。

    ![](https://hackmd.io/_uploads/Hkxezn5Pch.png)

這裡再舉個例子，假如你現在想建立目錄"my photo"，而你輸入：
```
mkdir my photo
```
得到的結果會是建立兩個資料夾，分別叫做"my"跟"photo"，所以切記：「空格是用來分隔參數的」！

## ■ shell 你是怎麼知道的？？？ ■
那現在可能會想問，當我輸入`date`或`echo`，shell是如何知道這些program是什麼？
![](https://hackmd.io/_uploads/SycF1iw93.png)

答案是，有一些內置程序，是你的計算機自帶的。就像你的電腦可能會附帶terminal，或附帶瀏覽器，它還會附帶一堆面向終端的應用程式，這些應用程式儲存在你的文件系統中，而你的shell有方法可以去確定程式的位置，亦即shell有一種搜尋程式的基本方法，而這種方法是透過一個叫「環境變數（environment variable）」的東西來實現的。

環境變數是一種變數，就像平常我們在用的程式語言中的變數一樣，這也證明了shell（尤其是Bash）真的是一種程式語言。

因此shell提示符（shell prompt）後方不僅能夠執行帶有參數的程式，你還可以做while loop、for loop、條件語句等等的事情，不只如此，你甚至可以在shell中定義函數、變數等等，這些事皆可以在shell中實現。

### ▋ $PATH
其中有個重要的變數，叫做路徑變數（`$path`），這個路徑變數會顯示出所有的路徑列表，而shell就是在這些路徑裡搜尋程式的。
```
echo $PATH
```
![](https://hackmd.io/_uploads/BkBl4ow5h.png)

印出來的內容即所有的路徑列表，用冒號（：）做區隔。
所以說每當你在shell上輸入程式的名稱之後，shell都會在計算機上搜尋這個路徑列表，並在每個資料夾中查找與你嘗試執行的程式匹配的內容。

因此當我執行`date`或`echo`時，它將會一個個遍歷整個路徑列表，直到找到名為`date`或`echo`的程式，然後執行它們。

### ▋ which
如果你想知道某個程式名稱，它實際上是運行哪個程式，則可以使用`which`來實現。

例如說我想知道`echo`實際是運行哪個路徑中的程式，我可以輸入：
```
which echo
```
![](https://hackmd.io/_uploads/S1sd8sw93.png)

它就會告訴我，如果我想執行名為`echo`的程式，它實際上會去執行`/usr/bin/echo`

## ■ 路徑 ■
路徑是一種「描述文件在電腦上的位置」方式。

**在Linux或mac OS中**
路徑是由正斜線（forward slashes，`/`）分隔的。在Linux或mac OS中，所有內容都是屬於在根命名空間（root namespace），所以所有絕對路徑都以`/`開頭。

**在Windows中**
路徑是由反斜線（backslashes，`\`）分隔的。在Windows上，每一個分區都會有一個根目錄，所以你可能會看到類似`c:\`或`D:\`之類的路徑，也就是說Windows的每個驅動器都有一個單獨的路徑結構。

### ▋ 絕對路徑
絕對路徑是完全內確定文件位置的路徑，從前面的例子，我們用which尋找echo的指令位置時，所到的結果即為一個絕對路徑。
```
/usr/bin/echo
```

### ▋ 相對路徑
相對路徑是相對於你目前所在位置的路徑。

### ▋ pwd
> pwd: print working directory (目錄)

而要找出你目前的位置，則是使用`pwd`，他將印出我目前的所在位置。
![](https://hackmd.io/_uploads/ByAA418s2.png)

從上圖可知，我目前在根目錄的home目錄中的noz目錄中。

### ▋ cd
而我們也可以利用`cd`更改我當前的工作目錄。
![](https://hackmd.io/_uploads/ryUxvyIj3.png)

從上圖可看到，我們執行了`cd /home`之後，我現在的位置來到了home目錄中。

:::warning
而這裡有幾個特殊的目錄，例如`.`（dot）、`..`（dot-dot）
1. **`.`（dot）**
`.`（dot）代表當前目錄
2. **`..`（dot-dot）**
`..`（dot-dot）代表父目錄
:::

接續上方目前所在home目錄底下輸入`cd ..`，代表著我要「前往」（`cd`代表前往），home目錄的「父目錄」（`..`代表父目錄），而home目錄的「父目錄」即根目錄。
![](https://hackmd.io/_uploads/r1KKdk8sh.png)

接著，打上`cd ./home`，代表著我要前往「當前目錄」下的home目錄（`.`代表當前目錄）
![](https://hackmd.io/_uploads/SkXNqyIjh.png)

所以若我接續上一步，再一次的打上`cd ./home`，他便會顯示找不到home目錄，畢竟我們當前目錄就是home目錄了。
![](https://hackmd.io/_uploads/SkHF5kIsn.png)

因此，我們還可以往深層去挖到一個bin目錄，bin目錄裡頭還有個echo文件，之後我可以做`echo "hello world"`，這將在bin目錄底下執行echo程式。
![](https://hackmd.io/_uploads/rygso1Uin.png)

所以從上方多個例子可知，這是透過建構路徑來遍歷文件系統的方法。

### ▋ ls
我們已經知道`pwd`可以印出你當前所在的位置，而這裡要介紹另外一個指令`ls`，`ls`可以列出你當前目錄中的所有文件。

我可以透過`ls`得知桌面上有哪些文件。
![](https://hackmd.io/_uploads/HkcR6J8o2.png)

而如果想看桌面的父目錄底下有哪些文件，我們其實有兩種實作方式：
1. 先透過`cd ..`回到父目錄，再下`ls`指令。
![](https://hackmd.io/_uploads/SJ1dR1Uj3.png)
2. 直接給予`ls`指令參數`..`，亦即`ls ..`。
![](https://hackmd.io/_uploads/Hy6s0J8ih.png)

:::warning
這裡再介紹另外兩種特殊符號
1. **`~`(telda，波浪符)**
    他會帶你到「主目錄」，也就是說`~`可以代替`/home/noz`。
    ![](https://hackmd.io/_uploads/rymdkgUj2.png)

2. **`-`（dash，連接號）**
    `-`對於`cd`指令也相當有幫助，如果使用`cd -`，他會帶你前往前一個你所在的目錄當中（有點像是回到上衣步驟的概念），所以這是一個非常方便的方法，讓你可以在兩個不同的目錄之間不停做切換。

    如下圖，便可以看見我透過`cd -`在modern-react-with-redux與主目錄間做切換。
    ![](https://hackmd.io/_uploads/SJuKll8sh.png)

:::

### ▋ 參數：- -help
在`cd`與`ls`中，還有很多其他參數和選項可以使用，只是我們可能不知道而已，大多數的指令、程式都會採用所謂的參數，例如flags（標誌）或options（選項），而這些flags（標誌）或options（選項）通常以`-`（dash）開頭。

其中一個方便的選項，便是`--help`，我們現在執行`ls --help`，他便會印出所有關於`ls`使用方式的所有信息。（下圖僅節圖一部份）

![](https://hackmd.io/_uploads/HJ2vXeIi2.png)

我們可以透過這行得知`...`可以放上零個、一個或多個的參數，而`[ ]`內則是optional的（可依使用者決定是否使用）
![](https://hackmd.io/_uploads/HJzWBgIi2.png)


從中，可以看到各種可以使用的flags或options，以及他們的詳細說明。

通常我們對於「單一dash＋單個字母」的組合以及「不帶任何值的內容」稱作為flag; 而「帶有值的內容」稱為選項。舉例來說，`-a`或`--all`為flag; `-c`或`--color`為option。

### ▋ ls -l
我們還可以從這長串列表找到一個`-l`，他的詳細說明為「使用較長格式列出訊息」。
![](https://hackmd.io/_uploads/SJGyUgUih.png)

實際使用他看看。首先，若我們單單執行`ls`，他會印出當前目錄下的所有文件。
![](https://hackmd.io/_uploads/Bkd9LgIi2.png)

而執行`ls -l`，同樣會印出當前目錄下的所有文件，但會發現他給予更多關於這些文件的詳細內容。
![](https://hackmd.io/_uploads/ryTPIxLi2.png)

那這些多出來的內容，又代表著什麼？
首先，看到前面一串長的很類似的字串：
![](https://hackmd.io/_uploads/SkUmLb8jh.jpg)

**第一個字母**：開頭若為`d`，代表著該項目為一個「目錄」，也就是說例如`arduino-web`、`t3`、`T3切版`等等為一個目錄，而`test`或是`index.html`則為文件。

**除去第一個字母之後，後面接著九個字母，每三個字母構成一組。**
首先，要知道有時候我們可能無法進入某一個目錄或無法打開某一個文件，這完全取決於文件或目錄設置的權限。

* **第一組**：表示為該文件的所有者設置的權限。
* **第二組**：表示為擁有該文件的group設置的權限。
* **第三組**：表示為其他人的權限（對於那些非文件或目錄所有者或group所有者）

從該圖可看到，使用者皆是我（noz）
![](https://hackmd.io/_uploads/ryTPIxLi2.png)

不過來到根目錄執行`ls -l`，可以看見所有者都變成root user。
![](https://hackmd.io/_uploads/HJ8PsxUoh.png)

:::danger
每一組中的三個字母，分別代表著讀取（Read）、寫入（write）、執行（execute），所以可以看見rwx，即是讀取、寫入、執行的意思。

**文件**
因此以文件來說：
* 若你有讀取權限，那你就可以閱讀他的內容
* 若你有寫入權限，那你就可以保存文件、添加更多內容或完全替換掉內容
* 若你有執行權限，那你就可以執行該文件。

例如，我現在執行`ls -l /usr/bin`，可以看到各種指令，其中我們可以發現他們皆存在x（x的位置沒有出現dash代表有執行的權限），即便是第三組字母也都為x（亦即即使不是該目錄或文件所有者也可以執行）。
![](https://hackmd.io/_uploads/BJpE6lUon.png)

有以上現象的原因非常簡單，這是因為我們希望電腦上的人都能執行這些程序，例如常見的`echo`或是`date`，我們沒有理由去限制只有部份的人可以使用`echo`，這沒有任何意義。

**目錄**
以目錄來說：
* 讀取的意思轉為「你是否被允許看到這個目錄中的文件？」
* 寫入意思則轉為「你是否被允許在該目錄中重新命名、創建或刪除文件？」
    > 所以可以想像，我們不允許寫入A目錄，但我們允許寫入A目錄底下的A文件，代表著我們「允許清空A文件」，但是「不被允許刪除A文件」。
* 執行權限代表「搜索權限」，即「你是否被允許進入該文件？」
    > 因此若我想使用`echo`，那麼我就必須要有根目錄、usr目錄、bin目錄執行權限，我才能一層層的進入這些目錄，並執行`echo`。
    > 
    > 若我沒有這些目錄的執行權限，我將不被允許執行`echo`，因為我將無法進入這些目錄。
:::

### ▋ mv
> mv: move

用於重新命名文件或移動文件到不同目錄中，他接受兩個參數，一個是當前的文件路徑，另一個則是目標文件的路徑。

舉例來說，當前目錄中有個A.md文件，我想將他重新命名為AAA.md：
```
mv A.md AAA.md
```

### ▋ cp
> cp: copy

用來複製文件，用法與`mv`指令相似，一樣接受兩個參數，一個是要複製的文件路徑，另一個是目標路徑。

舉例來說，當前目錄（當前目錄叫做currentD）有個A.md文件，我想將A.md文件複製到當前目錄的父目錄中：
```
cp A.md ../currentD
```

### ▋ rm、rmdir
> rm: remove
> rmdir: remove directory

rm 用來刪除文件或目錄的指令。
redir 用來刪除目錄，但只能刪除空目錄，這是一種安全機制。
![](https://hackmd.io/_uploads/BkJS5WLjh.png)

### ▋ mkdir
> mkdir: make directory

mkdir 用來創建新目錄。

### ▋ man
> man: manual pages（手冊頁）

如果想知道更多指令，可以使用`man`。這個指令以另外一個指令作為參數，舉例來說`man ls`，可以讓我們看見`ls`的手冊頁。

## ■ 在程式間創建連接 ■ 
我們希望不僅僅是執行`ls`、`cd`等等這樣單一的指令，我們希望可以與文件交互作用，讓文件在不同程式中傳輸，而這部份，我們可以透過shell提供的「流（streams）」的概念來實現。

每個程式都有兩種主要的「流（streams）」：輸入流（input stream）、輸出流（output stream）。

預設上，輸入流來自於你的鍵盤，指向終端機。當你在終端機上輸入任何內容便會進入程式，而輸出流就是每當程式印出輸出結果，預設上仍然指向你的終端。這就是為什麼，我在終端輸入`echo hello`，就會在終端印出`hello`。

### ▋ `< >`（angle bracket sign，尖括號）
不過，shell提供了重新定向這些流的方法，以改變輸入、輸出的指向，最簡單的方法是使用`< >`（angle bracket sign，尖括號）。

* **< file**
    表示這個程式的「輸入」重新定向為"file"文件的內容
* **> file**
    表示這個程式的「輸出」重新定向為"file"文件的內容
    
舉例來說，我從終端在桌面目錄下執行了`echo hello`，依照先前的經驗，很顯然地輸出會指向終端，因此會在終端印出`hello`：
![](https://hackmd.io/_uploads/rJ4HfzUsn.png)

不過我現在使用尖括號來重新定向輸出流，執行`echo hello > hello.txt`，該指令串後方的`> hello.txt`即代表我將輸出重新定向到`hello.txt`之上，這意味著`hello`將不再印在終端上，而是印到`hello.txt`上。

執行`echo hello > hello.txt`
![](https://hackmd.io/_uploads/HJPeXG8in.png)

執行後，會發現桌面多了一個檔案
![](https://hackmd.io/_uploads/BJtWXfIjh.png)

打開該檔案，會看到裡面印了一行`hello`
![](https://hackmd.io/_uploads/BJWLQMLi3.png)

### ▋ cat結合`< >`（angle bracket sign，尖括號）

當然，我們也可以利用`cat`指令，在終端上直接印出該文件中的內容。

`cat`指令可以印出文件的內容。
```
cat hello.txt
```
![](https://hackmd.io/_uploads/SJXPHMIj3.png)

結合`<`指定"輸入"程式的位置，我們把`hello.txt`的內容輸入指向cat，但我們這裡並沒有指定"輸出"的指向，所以預設輸出一樣到terminal上，所以得到與上方相同的結果：
```
cat < hello.txt
```
![](https://hackmd.io/_uploads/Hyh1rU30n.png)

我們也可同時使用`< >`（重新指定輸入、輸出的指向），例如說我想複製文件，但我不想用[`cp`指令](https://hackmd.io/xy9Xhag4R3Onlg-ucUy4yQ?both#%E2%96%8B-cp)，我想利用cat：
```
cat < hello.txt > hello2.txt
```

這會發生什麼事呢？我們先照著程式分析，首先，`cat < hello.txt`會將`hello.txt`的內容輸入到`cat`，接著是`> hello2.txt`代表要輸出到一個新文件`hello2.txt`裡。

這時桌面就會新創建一份`hello2.txt`，而裡頭的內容會完全複製於`hello.txt`。

我們也可以看見這時terminal上面不會有任何的輸出（因為已經輸出到`hello2.txt`裡了）

![](https://hackmd.io/_uploads/Hk2DU8nAn.png)

![](https://hackmd.io/_uploads/ryXjL8n02.png)

### ▋ `>>`（double end bracket）
用於"追加"文件。

我們若延續上方，重複輸入兩次`cat < hello.txt > hello2.txt`，會發現不管重複輸入幾次，在`hello2.txt`永遠都只輸出一次的hello。

這個時候就可以使用`>>`（double end bracket）：
```
cat < hello.txt >> hello2.txt
```
他可以讓我們輸出第二次，亦即追加輸出。
![](https://hackmd.io/_uploads/B1wlOInRh.png)

### ▋ `|`（pipe character，管道符）
`|`（pipe character，管道符）的作用是將管道符號「左邊程式的輸出」作為「右邊程式的輸入」。

1. tail -n1
    那首先我們先知道一下一個指令叫做`tail`，他可以印出內容的最後n行，再加上使用參數`-n1`讓程式只印出最後1行（或者使用`--line=1`）

2. ls -l /
    並且重新複習一下[`ls -l`指令](https://hackmd.io/xy9Xhag4R3Onlg-ucUy4yQ?both#%E2%96%8B-ls--l)，`ls`是列出當前目錄中的所有文件，再加上參數`-l`則讓程式使用較長格式列印出訊息（i.e.更詳細印出訊息），而`/`為根命名空間（root namespace）。

tail跟ls兩種指令是完全不相干的程式，不過我們現在將上述兩種指令搭配管道符號使用，從管道符號的作用可大略知道，他會將`ls -l`的輸出成為`tail -n1`的輸入，然後`tail -n1`的輸出會到terminal。

這個時候，我們就成功將兩個不相關，原先不能用在一起的兩個指令給用在一起了！以下程式將印出ls-l的所有輸出中最後一行內容：
```
ls -l / | tail -n1
```

![](https://hackmd.io/_uploads/SJju283Rh.png)

會在後面章節更詳細介紹`|`（pipe character，管道符）。
這裡我自己的理解如下圖：

![](https://hackmd.io/_uploads/ry4Q1DnR3.png)

## ■ 一個功能全面又強大的工具 ■ 
對於大多數的類unix系統（macOS、linux）都有一個很重要的主題，即root使用者（root user），root user在windows上有點類似管理員用戶（administrator user），root user是非常特別的，他可以在系統上做任何的事情（即便檔案是不可讀、不可寫的）

但大多數的時間，我們不會作為root user這樣的超級使用者來操作，你會用可能John、May...或其他名字來成為一名使用者，因為若你一直作為root user來操作你的電腦，如果你運行了錯誤的指令，那麼可能會完全的毀掉你的電腦，這不會是我們所希望發生的事情。

不過偶爾我們還是希望可以作為root user去操作電腦，而在一般情況下，你會使用一個叫做`sudo`的指令。顧名思義，就是讓你以su的身份去操作電腦（su即super user的意思，亦即使用了`sudo`就可以讓你以super user也就是root user的身份去操作任何指令）

### ▋ `sudo`

那什麼時候會使用到`sudo`這個指令呢？
在我們的電腦中有許多特殊的文件，例如說有一個叫做sysfs的文件系統。

我們進到sys檔案中，並且看看這個檔案裡面有什麼內容
```
cd /sys
ls
```
![](https://hackmd.io/_uploads/rkRlQD3Ah.png)

我們會發現一個新世界，這些文件實際上並不在我們的電腦裡面，而是各種"kernel parameter（內核參數）"，kernel就像是你電腦的核心，你可以透過文件系統來訪問各種kernel parameter

例如說，我們在進入到class，並且看看裡面的內容：
```
cd class/
ls
```
![](https://hackmd.io/_uploads/H1NAQP2Ch.png)

我們可以看見許多文件，而既然他們是文件，代表著我們可以利用所有先前學到的所有指令來操作他們

再舉個例子，我們這時候再進入一個backlight的文件，再看看裡面有什麼：（backlight用於處理電腦螢幕的背光燈）

```
cd backlight/
ls
```
![](https://hackmd.io/_uploads/S15nVwnA3.png)

接著我們繼續進入intel_backlight文件，並查看裡頭的內容：
```
cd intel_backlight/
ls
```
![](https://hackmd.io/_uploads/B1XBHv202.png)

我們可以看見裡面有個`brightness`文件，我們用`cat`指令將它的內容印出來：
```
cat brightness
```
![](https://hackmd.io/_uploads/SJoqHwnA2.png)

從上圖可看見我目前螢幕的亮度為"46"。不僅如此，我還可以修改這個螢幕亮度，所以現在可能會想把之前所學趕快運用上來，於是滿心期待的打上下方程式

[`echo`指令](https://hackmd.io/xy9Xhag4R3Onlg-ucUy4yQ?both#%E2%96%8B-echo)可以print出你給予他的參數（這裡的參數是"500"），而`>`表指定輸出指向到後方參數"brightness文件"，也就是說brightness文件的內容變為500：
```
echo 500 > brightness
```

但結果卻不如我們預期，電腦拒絕了我們的指令：
![](https://hackmd.io/_uploads/BynVPPhCn.png)

而這是因為我們若想修改kernel裡面的內容，就必須變成管理員，也就是root user。這時，你可能會想說那我就在前方加上`sudo`就解決啦！

```
sudo echo 500 > brightness
```
但結果仍是被拒絕了QQ
![](https://hackmd.io/_uploads/HkusPP3A3.png)

這是因為我們先前提到的，輸入與輸出的流向，程式、指令是不知道的，就想前面我們想把ls傳給tail，但tail並不認識ls，ls也不認識tail，因為通道（pipe）及輸出輸入的重定向（redirection）是由shell設置的。

所以在上方這個case中，我們應該要告訴shell要運行`sudo`，並且使用參數`echo`以及`500`，並將輸出發送到"brightness文件"。

但是shell是打開"brightness文件"的東西，不是`sudo`去打開，所以在這情況中，作為我運行的shell嘗試打開"brightness文件"進行寫入，而這是不被允許的，因此我會收到權限被拒絕的錯誤。

我們可以在shell中看見"$"，這代表著我們不是用root 的身份在運行shell，這就是為什麼我們會被拒絕。

所以這裡提供一個方法，他可以讓我們轉換到root terminal
```
sudo su
//他會要求我們輸入密碼，輸入完即切換到root terminal
//若要離開root user
exit
```
![](https://hackmd.io/_uploads/ByvuoP3Cn.png)

還可以看到從原先的user name "noz"變成了"root"。
![](https://hackmd.io/_uploads/S1Hy2vhRn.png)

這個時候再次輸入：
```
echo 500 > brightness
```
會發現他不再拒絕權限了！而且也成功更改了電腦螢幕亮度。
![](https://hackmd.io/_uploads/Hywv2vh03.png)

＃＃＃

不過到現在我們對terminal的所知，除了上方「以root身份運行shell」的方法之外，其實還有另一種方法，即利用`|`（pipe character，管道符）：
```
echo 500 | sudo tee brightness 
```

結果一樣試行得通得（但我懶得再試了）
這裡的不同在於，我告訴shell我要運行`echo 500`的指令，所以他會印出500，然後我還告訴shell我要執行`sudo tee brightness`指令，並讓「`echo 500`的輸出」作為「`sudo tee`的輸入」（`tee`指令會將輸入內容寫進一個文件中，同時也會輸出，而這裡將輸入內容寫進brightness文件）

### ▋ `xdg-open`
從開始到現在，都一直在提如何查找文件。這裡有個方法可以打開文件：
```
xdg-open hello2.txt
```

![](https://hackmd.io/_uploads/Byofp4pA2.png)

輸入指令之後，終端機會幫我們打開`hello2.txt`文件
![](https://hackmd.io/_uploads/ryxH6NT03.png)

****

## ■ 習題與解答 ■
missing semester L1 [習題與解答](https://missing-semester-cn.github.io/missing-notes-and-solutions/2020/solutions/course-shell-solution/)