# 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/)